AccessibilityManagerService.java revision 49782e46c0eb85a25ae2abcf80880c48dbab5aea
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.database.ContentObserver;
42import android.graphics.Point;
43import android.graphics.Rect;
44import android.hardware.display.DisplayManager;
45import android.hardware.input.InputManager;
46import android.net.Uri;
47import android.opengl.Matrix;
48import android.os.Binder;
49import android.os.Build;
50import android.os.Bundle;
51import android.os.Handler;
52import android.os.IBinder;
53import android.os.Looper;
54import android.os.Message;
55import android.os.Parcel;
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.IWindowManager;
73import android.view.InputDevice;
74import android.view.InputEventConsistencyVerifier;
75import android.view.KeyCharacterMap;
76import android.view.KeyEvent;
77import android.view.MagnificationSpec;
78import android.view.WindowManager;
79import android.view.WindowManagerPolicy;
80import android.view.accessibility.AccessibilityEvent;
81import android.view.accessibility.AccessibilityInteractionClient;
82import android.view.accessibility.AccessibilityManager;
83import android.view.accessibility.AccessibilityNodeInfo;
84import android.view.accessibility.IAccessibilityInteractionConnection;
85import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
86import android.view.accessibility.IAccessibilityManager;
87import android.view.accessibility.IAccessibilityManagerClient;
88
89import com.android.internal.R;
90import com.android.internal.content.PackageMonitor;
91import com.android.internal.statusbar.IStatusBarService;
92
93import org.xmlpull.v1.XmlPullParserException;
94
95import java.io.FileDescriptor;
96import java.io.IOException;
97import java.io.PrintWriter;
98import java.util.ArrayList;
99import java.util.Arrays;
100import java.util.Collections;
101import java.util.HashMap;
102import java.util.HashSet;
103import java.util.Iterator;
104import java.util.List;
105import java.util.Map;
106import java.util.Set;
107import java.util.concurrent.CopyOnWriteArrayList;
108
109/**
110 * This class is instantiated by the system as a system level service and can be
111 * accessed only by the system. The task of this service is to be a centralized
112 * event dispatch for {@link AccessibilityEvent}s generated across all processes
113 * on the device. Events are dispatched to {@link AccessibilityService}s.
114 *
115 * @hide
116 */
117public class AccessibilityManagerService extends IAccessibilityManager.Stub {
118
119    private static final boolean DEBUG = false;
120
121    private static final String LOG_TAG = "AccessibilityManagerService";
122
123    // TODO: This is arbitrary. When there is time implement this by watching
124    //       when that accessibility services are bound.
125    private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
126
127    private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
128        "registerUiTestAutomationService";
129
130    private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
131            "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
132
133    private static final ComponentName sFakeAccessibilityServiceComponentName =
134            new ComponentName("foo.bar", "FakeService");
135
136    private static final String FUNCTION_DUMP = "dump";
137
138    private static final char COMPONENT_NAME_SEPARATOR = ':';
139
140    private static final int OWN_PROCESS_ID = android.os.Process.myPid();
141
142    private static final int MAX_POOL_SIZE = 10;
143
144    private static int sIdCounter = 0;
145
146    private static int sNextWindowId;
147
148    private final Context mContext;
149
150    private final Object mLock = new Object();
151
152    private final Pool<PendingEvent> mPendingEventPool =
153            new SimplePool<PendingEvent>(MAX_POOL_SIZE);
154
155    private final SimpleStringSplitter mStringColonSplitter =
156            new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
157
158    private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
159            new ArrayList<AccessibilityServiceInfo>();
160
161    private final Rect mTempRect = new Rect();
162
163    private final Point mTempPoint = new Point();
164
165    private final Display mDefaultDisplay;
166
167    private final PackageManager mPackageManager;
168
169    private final IWindowManager mWindowManagerService;
170
171    private final SecurityPolicy mSecurityPolicy;
172
173    private final MainHandler mMainHandler;
174
175    private Service mQueryBridge;
176
177    private AlertDialog mEnableTouchExplorationDialog;
178
179    private AccessibilityInputFilter mInputFilter;
180
181    private boolean mHasInputFilter;
182
183    private final Set<ComponentName> mTempComponentNameSet = new HashSet<ComponentName>();
184
185    private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
186            new ArrayList<AccessibilityServiceInfo>();
187
188    private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
189            new RemoteCallbackList<IAccessibilityManagerClient>();
190
191    private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
192            new SparseArray<AccessibilityConnectionWrapper>();
193
194    private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<IBinder>();
195
196    private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
197
198    private int mCurrentUserId = UserHandle.USER_OWNER;
199
200    //TODO: Remove this hack
201    private boolean mInitialized;
202
203    private UserState getCurrentUserStateLocked() {
204        return getUserStateLocked(mCurrentUserId);
205    }
206
207    private UserState getUserStateLocked(int userId) {
208        UserState state = mUserStates.get(userId);
209        if (state == null) {
210            state = new UserState(userId);
211            mUserStates.put(userId, state);
212        }
213        return state;
214    }
215
216    /**
217     * Creates a new instance.
218     *
219     * @param context A {@link Context} instance.
220     */
221    public AccessibilityManagerService(Context context) {
222        mContext = context;
223        mPackageManager = mContext.getPackageManager();
224        mWindowManagerService = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
225        mSecurityPolicy = new SecurityPolicy();
226        mMainHandler = new MainHandler(mContext.getMainLooper());
227        //TODO: (multi-display) We need to support multiple displays.
228        DisplayManager displayManager = (DisplayManager)
229                mContext.getSystemService(Context.DISPLAY_SERVICE);
230        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
231        registerBroadcastReceivers();
232        new AccessibilityContentObserver(mMainHandler).register(
233                context.getContentResolver());
234    }
235
236    private void registerBroadcastReceivers() {
237        PackageMonitor monitor = new PackageMonitor() {
238            @Override
239            public void onSomePackagesChanged() {
240                synchronized (mLock) {
241                    if (getChangingUserId() != mCurrentUserId) {
242                        return;
243                    }
244                    // We will update when the automation service dies.
245                    UserState userState = getCurrentUserStateLocked();
246                    // We have to reload the installed services since some services may
247                    // have different attributes, resolve info (does not support equals),
248                    // etc. Remove them then to force reload. Do it even if automation is
249                    // running since when it goes away, we will have to reload as well.
250                    userState.mInstalledServices.clear();
251                    if (userState.mUiAutomationService == null) {
252                        if (readConfigurationForUserStateLocked(userState)) {
253                            onUserStateChangedLocked(userState);
254                        }
255                    }
256                }
257            }
258
259            @Override
260            public void onPackageRemoved(String packageName, int uid) {
261                synchronized (mLock) {
262                    final int userId = getChangingUserId();
263                    if (userId != mCurrentUserId) {
264                        return;
265                    }
266                    UserState userState = getUserStateLocked(userId);
267                    Iterator<ComponentName> it = userState.mEnabledServices.iterator();
268                    while (it.hasNext()) {
269                        ComponentName comp = it.next();
270                        String compPkg = comp.getPackageName();
271                        if (compPkg.equals(packageName)) {
272                            it.remove();
273                            // Update the enabled services setting.
274                            persistComponentNamesToSettingLocked(
275                                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
276                                    userState.mEnabledServices, userId);
277                            // Update the touch exploration granted services setting.
278                            userState.mTouchExplorationGrantedServices.remove(comp);
279                            persistComponentNamesToSettingLocked(
280                                    Settings.Secure.
281                                    TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
282                                    userState.mTouchExplorationGrantedServices, userId);
283                            // We will update when the automation service dies.
284                            if (userState.mUiAutomationService == null) {
285                                onUserStateChangedLocked(userState);
286                            }
287                            return;
288                        }
289                    }
290                }
291            }
292
293            @Override
294            public boolean onHandleForceStop(Intent intent, String[] packages,
295                    int uid, boolean doit) {
296                synchronized (mLock) {
297                    final int userId = getChangingUserId();
298                    if (userId != mCurrentUserId) {
299                        return false;
300                    }
301                    UserState userState = getUserStateLocked(userId);
302                    Iterator<ComponentName> it = userState.mEnabledServices.iterator();
303                    while (it.hasNext()) {
304                        ComponentName comp = it.next();
305                        String compPkg = comp.getPackageName();
306                        for (String pkg : packages) {
307                            if (compPkg.equals(pkg)) {
308                                if (!doit) {
309                                    return true;
310                                }
311                                it.remove();
312                                persistComponentNamesToSettingLocked(
313                                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
314                                        userState.mEnabledServices, userId);
315                                // We will update when the automation service dies.
316                                if (userState.mUiAutomationService == null) {
317                                    onUserStateChangedLocked(userState);
318                                }
319                            }
320                        }
321                    }
322                    return false;
323                }
324            }
325        };
326
327        // package changes
328        monitor.register(mContext, null,  UserHandle.ALL, true);
329
330        // user change and unlock
331        IntentFilter intentFilter = new IntentFilter();
332        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
333        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
334        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
335
336        mContext.registerReceiverAsUser(new BroadcastReceiver() {
337            @Override
338            public void onReceive(Context context, Intent intent) {
339                String action = intent.getAction();
340                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
341                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
342                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
343                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
344                } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
345                    // We will update when the automation service dies.
346                    UserState userState = getCurrentUserStateLocked();
347                    if (userState.mUiAutomationService == null) {
348                        if (readConfigurationForUserStateLocked(userState)) {
349                            onUserStateChangedLocked(userState);
350                        }
351                    }
352                }
353            }
354        }, UserHandle.ALL, intentFilter, null, null);
355    }
356
357    public int addClient(IAccessibilityManagerClient client, int userId) {
358        synchronized (mLock) {
359            final int resolvedUserId = mSecurityPolicy
360                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
361            // If the client is from a process that runs across users such as
362            // the system UI or the system we add it to the global state that
363            // is shared across users.
364            UserState userState = getUserStateLocked(resolvedUserId);
365            if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
366                mGlobalClients.register(client);
367                if (DEBUG) {
368                    Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
369                }
370                return userState.getClientState();
371            } else {
372                userState.mClients.register(client);
373                // If this client is not for the current user we do not
374                // return a state since it is not for the foreground user.
375                // We will send the state to the client on a user switch.
376                if (DEBUG) {
377                    Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
378                            + " and userId:" + mCurrentUserId);
379                }
380                return (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0;
381            }
382        }
383    }
384
385    public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
386        synchronized (mLock) {
387            final int resolvedUserId = mSecurityPolicy
388                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
389            // This method does nothing for a background user.
390            if (resolvedUserId != mCurrentUserId) {
391                return true; // yes, recycle the event
392            }
393            if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
394                mSecurityPolicy.updateEventSourceLocked(event);
395                mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW,
396                        event.getWindowId(), event.getEventType()).sendToTarget();
397                notifyAccessibilityServicesDelayedLocked(event, false);
398                notifyAccessibilityServicesDelayedLocked(event, true);
399            }
400            if (mHasInputFilter && mInputFilter != null) {
401                mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
402                        AccessibilityEvent.obtain(event)).sendToTarget();
403            }
404            event.recycle();
405            getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
406        }
407        return (OWN_PROCESS_ID != Binder.getCallingPid());
408    }
409
410    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
411        synchronized (mLock) {
412            final int resolvedUserId = mSecurityPolicy
413                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
414            // The automation service is a fake one and should not be reported
415            // to clients as being installed - it really is not.
416            UserState userState = getUserStateLocked(resolvedUserId);
417            if (userState.mUiAutomationService != null) {
418                List<AccessibilityServiceInfo> installedServices =
419                        new ArrayList<AccessibilityServiceInfo>();
420                installedServices.addAll(userState.mInstalledServices);
421                installedServices.remove(userState.mUiAutomationService);
422                return installedServices;
423            }
424            return userState.mInstalledServices;
425        }
426    }
427
428    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
429            int userId) {
430        List<AccessibilityServiceInfo> result = null;
431        synchronized (mLock) {
432            final int resolvedUserId = mSecurityPolicy
433                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
434
435            // The automation service is a fake one and should not be reported
436            // to clients as being enabled. The automation service is always the
437            // only active one, if it exists.
438            UserState userState = getUserStateLocked(resolvedUserId);
439            if (userState.mUiAutomationService != null) {
440                return Collections.emptyList();
441            }
442
443            result = mEnabledServicesForFeedbackTempList;
444            result.clear();
445            List<Service> services = userState.mBoundServices;
446            while (feedbackType != 0) {
447                final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
448                feedbackType &= ~feedbackTypeBit;
449                final int serviceCount = services.size();
450                for (int i = 0; i < serviceCount; i++) {
451                    Service service = services.get(i);
452                    if ((service.mFeedbackType & feedbackTypeBit) != 0) {
453                        result.add(service.mAccessibilityServiceInfo);
454                    }
455                }
456            }
457        }
458        return result;
459    }
460
461    public void interrupt(int userId) {
462        CopyOnWriteArrayList<Service> services;
463        synchronized (mLock) {
464            final int resolvedUserId = mSecurityPolicy
465                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
466            // This method does nothing for a background user.
467            if (resolvedUserId != mCurrentUserId) {
468                return;
469            }
470            services = getUserStateLocked(resolvedUserId).mBoundServices;
471        }
472        for (int i = 0, count = services.size(); i < count; i++) {
473            Service service = services.get(i);
474            try {
475                service.mServiceInterface.onInterrupt();
476            } catch (RemoteException re) {
477                Slog.e(LOG_TAG, "Error during sending interrupt request to "
478                    + service.mService, re);
479            }
480        }
481    }
482
483    public int addAccessibilityInteractionConnection(IWindow windowToken,
484            IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
485        synchronized (mLock) {
486            final int resolvedUserId = mSecurityPolicy
487                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);
488            final int windowId = sNextWindowId++;
489            // If the window is from a process that runs across users such as
490            // the system UI or the system we add it to the global state that
491            // is shared across users.
492            if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
493                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
494                        windowId, connection, UserHandle.USER_ALL);
495                wrapper.linkToDeath();
496                mGlobalInteractionConnections.put(windowId, wrapper);
497                mGlobalWindowTokens.put(windowId, windowToken.asBinder());
498                if (DEBUG) {
499                    Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
500                            + " with windowId: " + windowId);
501                }
502            } else {
503                AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
504                        windowId, connection, resolvedUserId);
505                wrapper.linkToDeath();
506                UserState userState = getUserStateLocked(resolvedUserId);
507                userState.mInteractionConnections.put(windowId, wrapper);
508                userState.mWindowTokens.put(windowId, windowToken.asBinder());
509                if (DEBUG) {
510                    Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
511                            + " with windowId: " + windowId + " and userId:" + mCurrentUserId);
512                }
513            }
514            if (DEBUG) {
515                Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
516            }
517            return windowId;
518        }
519    }
520
521    public void removeAccessibilityInteractionConnection(IWindow window) {
522        synchronized (mLock) {
523            mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
524                    UserHandle.getCallingUserId());
525            IBinder token = window.asBinder();
526            final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
527                    token, mGlobalWindowTokens, mGlobalInteractionConnections);
528            if (removedWindowId >= 0) {
529                if (DEBUG) {
530                    Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
531                            + " with windowId: " + removedWindowId);
532                }
533                return;
534            }
535            final int userCount = mUserStates.size();
536            for (int i = 0; i < userCount; i++) {
537                UserState userState = mUserStates.valueAt(i);
538                final int removedWindowIdForUser =
539                        removeAccessibilityInteractionConnectionInternalLocked(
540                        token, userState.mWindowTokens, userState.mInteractionConnections);
541                if (removedWindowIdForUser >= 0) {
542                    if (DEBUG) {
543                        Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
544                                + " with windowId: " + removedWindowIdForUser + " and userId:"
545                                + mUserStates.keyAt(i));
546                    }
547                    return;
548                }
549            }
550        }
551    }
552
553    private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
554            SparseArray<IBinder> windowTokens,
555            SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
556        final int count = windowTokens.size();
557        for (int i = 0; i < count; i++) {
558            if (windowTokens.valueAt(i) == windowToken) {
559                final int windowId = windowTokens.keyAt(i);
560                windowTokens.removeAt(i);
561                AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
562                wrapper.unlinkToDeath();
563                interactionConnections.remove(windowId);
564                return windowId;
565            }
566        }
567        return -1;
568    }
569
570    public void registerUiTestAutomationService(IBinder owner,
571            IAccessibilityServiceClient serviceClient,
572            AccessibilityServiceInfo accessibilityServiceInfo) {
573        mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
574                FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
575
576        accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName);
577
578        synchronized (mLock) {
579            UserState userState = getCurrentUserStateLocked();
580
581            if (userState.mUiAutomationService != null) {
582                throw new IllegalStateException("UiAutomationService " + serviceClient
583                        + "already registered!");
584            }
585
586            try {
587                owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0);
588            } catch (RemoteException re) {
589                Slog.e(LOG_TAG, "Couldn't register for the death of a"
590                        + " UiTestAutomationService!", re);
591                return;
592            }
593
594            userState.mUiAutomationServiceOwner = owner;
595            userState.mUiAutomationServiceClient = serviceClient;
596
597            // Set the temporary state.
598            userState.mIsAccessibilityEnabled = true;
599            userState.mIsTouchExplorationEnabled = false;
600            userState.mIsEnhancedWebAccessibilityEnabled = false;
601            userState.mIsDisplayMagnificationEnabled = false;
602            userState.mInstalledServices.add(accessibilityServiceInfo);
603            userState.mEnabledServices.clear();
604            userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
605            userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName);
606
607            // Use the new state instead of settings.
608            onUserStateChangedLocked(userState);
609        }
610    }
611
612    public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
613        synchronized (mLock) {
614            UserState userState = getCurrentUserStateLocked();
615            // Automation service is not bound, so pretend it died to perform clean up.
616            if (userState.mUiAutomationService != null
617                    && serviceClient != null
618                    && userState.mUiAutomationService != null
619                    && userState.mUiAutomationService.mServiceInterface != null
620                    && userState.mUiAutomationService.mServiceInterface.asBinder()
621                    == serviceClient.asBinder()) {
622                userState.mUiAutomationService.binderDied();
623            } else {
624                throw new IllegalStateException("UiAutomationService " + serviceClient
625                        + " not registered!");
626            }
627        }
628    }
629
630    public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
631            ComponentName service, boolean touchExplorationEnabled) {
632        mSecurityPolicy.enforceCallingPermission(
633                Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
634                TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
635        try {
636            if (!mWindowManagerService.isKeyguardLocked()) {
637                return;
638            }
639        } catch (RemoteException re) {
640            return;
641        }
642        synchronized (mLock) {
643            // Set the temporary state.
644            UserState userState = getCurrentUserStateLocked();
645
646            // This is a nop if UI automation is enabled.
647            if (userState.mUiAutomationService != null) {
648                return;
649            }
650
651            userState.mIsAccessibilityEnabled = true;
652            userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
653            userState.mIsEnhancedWebAccessibilityEnabled = false;
654            userState.mIsDisplayMagnificationEnabled = false;
655            userState.mEnabledServices.clear();
656            userState.mEnabledServices.add(service);
657            userState.mBindingServices.clear();
658            userState.mTouchExplorationGrantedServices.clear();
659            userState.mTouchExplorationGrantedServices.add(service);
660
661            // User the current state instead settings.
662            onUserStateChangedLocked(userState);
663        }
664    }
665
666    boolean onGesture(int gestureId) {
667        synchronized (mLock) {
668            boolean handled = notifyGestureLocked(gestureId, false);
669            if (!handled) {
670                handled = notifyGestureLocked(gestureId, true);
671            }
672            return handled;
673        }
674    }
675
676    boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
677        synchronized (mLock) {
678            KeyEvent localClone = KeyEvent.obtain(event);
679            boolean handled = notifyKeyEventLocked(localClone, policyFlags, false);
680            if (!handled) {
681                handled = notifyKeyEventLocked(localClone, policyFlags, true);
682            }
683            return handled;
684        }
685    }
686
687    /**
688     * Gets the bounds of the accessibility focus in the active window.
689     *
690     * @param outBounds The output to which to write the focus bounds.
691     * @return Whether accessibility focus was found and the bounds are populated.
692     */
693    // TODO: (multi-display) Make sure this works for multiple displays.
694    boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
695        // Instead of keeping track of accessibility focus events per
696        // window to be able to find the focus in the active window,
697        // we take a stateless approach and look it up. This is fine
698        // since we do this only when the user clicks/long presses.
699        Service service = getQueryBridge();
700        final int connectionId = service.mId;
701        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
702        client.addConnection(connectionId, service);
703        try {
704            AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
705                    .getRootInActiveWindow(connectionId);
706            if (root == null) {
707                return false;
708            }
709            AccessibilityNodeInfo focus = root.findFocus(
710                    AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
711            if (focus == null) {
712                return false;
713            }
714            focus.getBoundsInScreen(outBounds);
715
716            MagnificationSpec spec = service.getCompatibleMagnificationSpec(focus.getWindowId());
717            if (spec != null && !spec.isNop()) {
718                outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
719                outBounds.scale(1 / spec.scale);
720            }
721
722            // Clip to the window rectangle.
723            Rect windowBounds = mTempRect;
724            getActiveWindowBounds(windowBounds);
725            outBounds.intersect(windowBounds);
726            // Clip to the screen rectangle.
727            mDefaultDisplay.getRealSize(mTempPoint);
728            outBounds.intersect(0,  0,  mTempPoint.x, mTempPoint.y);
729
730            return true;
731        } finally {
732            client.removeConnection(connectionId);
733        }
734    }
735
736    /**
737     * Gets the bounds of the active window.
738     *
739     * @param outBounds The output to which to write the bounds.
740     */
741    boolean getActiveWindowBounds(Rect outBounds) {
742        IBinder token;
743        synchronized (mLock) {
744            final int windowId = mSecurityPolicy.mActiveWindowId;
745            token = mGlobalWindowTokens.get(windowId);
746            if (token == null) {
747                token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
748            }
749        }
750        try {
751            mWindowManagerService.getWindowFrame(token, outBounds);
752            if (!outBounds.isEmpty()) {
753                return true;
754            }
755        } catch (RemoteException re) {
756            /* ignore */
757        }
758        return false;
759    }
760
761    int getActiveWindowId() {
762        return mSecurityPolicy.mActiveWindowId;
763    }
764
765    void onTouchInteractionStart() {
766        mSecurityPolicy.onTouchInteractionStart();
767    }
768
769    void onTouchInteractionEnd() {
770        mSecurityPolicy.onTouchInteractionEnd();
771    }
772
773    void onMagnificationStateChanged() {
774        notifyClearAccessibilityNodeInfoCacheLocked();
775    }
776
777    private void switchUser(int userId) {
778        synchronized (mLock) {
779            if (mCurrentUserId == userId && mInitialized) {
780                return;
781            }
782
783            // Disconnect from services for the old user.
784            UserState oldUserState = getUserStateLocked(mCurrentUserId);
785            oldUserState.onSwitchToAnotherUser();
786
787            // Disable the local managers for the old user.
788            if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
789                mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
790                        oldUserState.mUserId, 0).sendToTarget();
791            }
792
793            // Announce user changes only if more that one exist.
794            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
795            final boolean announceNewUser = userManager.getUsers().size() > 1;
796
797            // The user changed.
798            mCurrentUserId = userId;
799
800            UserState userState = getCurrentUserStateLocked();
801            if (userState.mUiAutomationService != null) {
802                // Switching users disables the UI automation service.
803                userState.mUiAutomationService.binderDied();
804            }
805
806            readConfigurationForUserStateLocked(userState);
807            // Even if reading did not yield change, we have to update
808            // the state since the context in which the current user
809            // state was used has changed since it was inactive.
810            onUserStateChangedLocked(userState);
811
812            if (announceNewUser) {
813                // Schedule announcement of the current user if needed.
814                mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
815                        WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
816            }
817        }
818    }
819
820    private void removeUser(int userId) {
821        synchronized (mLock) {
822            mUserStates.remove(userId);
823        }
824    }
825
826    private Service getQueryBridge() {
827        if (mQueryBridge == null) {
828            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
829            info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
830            mQueryBridge = new Service(UserHandle.USER_NULL,
831                    sFakeAccessibilityServiceComponentName, info);
832        }
833        return mQueryBridge;
834    }
835
836    private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
837        // TODO: Now we are giving the gestures to the last enabled
838        //       service that can handle them which is the last one
839        //       in our list since we write the last enabled as the
840        //       last record in the enabled services setting. Ideally,
841        //       the user should make the call which service handles
842        //       gestures. However, only one service should handle
843        //       gestures to avoid user frustration when different
844        //       behavior is observed from different combinations of
845        //       enabled accessibility services.
846        UserState state = getCurrentUserStateLocked();
847        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
848            Service service = state.mBoundServices.get(i);
849            if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
850                service.notifyGesture(gestureId);
851                return true;
852            }
853        }
854        return false;
855    }
856
857    private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) {
858        // TODO: Now we are giving the key events to the last enabled
859        //       service that can handle them Ideally, the user should
860        //       make the call which service handles key events. However,
861        //       only one service should handle key events to avoid user
862        //       frustration when different behavior is observed from
863        //       different combinations of enabled accessibility services.
864        UserState state = getCurrentUserStateLocked();
865        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
866            Service service = state.mBoundServices.get(i);
867            // Key events are handled only by services that declared
868            // this capability and requested to filter key events.
869            if (!service.mRequestFilterKeyEvents ||
870                    (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo
871                            .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
872                continue;
873            }
874            if (service.mIsDefault == isDefault) {
875                service.notifyKeyEvent(event, policyFlags);
876                return true;
877            }
878        }
879        return false;
880    }
881
882    private void notifyClearAccessibilityNodeInfoCacheLocked() {
883        UserState state = getCurrentUserStateLocked();
884        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
885            Service service = state.mBoundServices.get(i);
886            service.notifyClearAccessibilityNodeInfoCache();
887        }
888    }
889
890    /**
891     * Removes an AccessibilityInteractionConnection.
892     *
893     * @param windowId The id of the window to which the connection is targeted.
894     * @param userId The id of the user owning the connection. UserHandle.USER_ALL
895     *     if global.
896     */
897    private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
898        if (userId == UserHandle.USER_ALL) {
899            mGlobalWindowTokens.remove(windowId);
900            mGlobalInteractionConnections.remove(windowId);
901        } else {
902            UserState userState = getCurrentUserStateLocked();
903            userState.mWindowTokens.remove(windowId);
904            userState.mInteractionConnections.remove(windowId);
905        }
906        if (DEBUG) {
907            Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
908        }
909    }
910
911    private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
912        mTempAccessibilityServiceInfoList.clear();
913
914        List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
915                new Intent(AccessibilityService.SERVICE_INTERFACE),
916                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
917                mCurrentUserId);
918
919        for (int i = 0, count = installedServices.size(); i < count; i++) {
920            ResolveInfo resolveInfo = installedServices.get(i);
921            ServiceInfo serviceInfo = resolveInfo.serviceInfo;
922            if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
923                    serviceInfo.permission)) {
924                Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
925                        serviceInfo.packageName, serviceInfo.name).flattenToShortString()
926                        + ": it does not require the permission "
927                        + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
928                continue;
929            }
930            AccessibilityServiceInfo accessibilityServiceInfo;
931            try {
932                accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
933                mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
934            } catch (XmlPullParserException xppe) {
935                Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
936            } catch (IOException ioe) {
937                Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", ioe);
938            }
939        }
940
941        if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
942            userState.mInstalledServices.clear();
943            userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
944            mTempAccessibilityServiceInfoList.clear();
945            return true;
946        }
947
948        mTempAccessibilityServiceInfoList.clear();
949        return false;
950    }
951
952    private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
953        mTempComponentNameSet.clear();
954        readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
955                userState.mUserId, mTempComponentNameSet);
956        if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
957            userState.mEnabledServices.clear();
958            userState.mEnabledServices.addAll(mTempComponentNameSet);
959            mTempComponentNameSet.clear();
960            return true;
961        }
962        mTempComponentNameSet.clear();
963        return false;
964    }
965
966    private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
967            UserState userState) {
968        mTempComponentNameSet.clear();
969        readComponentNamesFromSettingLocked(
970                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
971                userState.mUserId, mTempComponentNameSet);
972        if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
973            userState.mTouchExplorationGrantedServices.clear();
974            userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
975            mTempComponentNameSet.clear();
976            return true;
977        }
978        mTempComponentNameSet.clear();
979        return false;
980    }
981
982    /**
983     * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
984     * and denotes the period after the last event before notifying the service.
985     *
986     * @param event The event.
987     * @param isDefault True to notify default listeners, not default services.
988     */
989    private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
990            boolean isDefault) {
991        try {
992            UserState state = getCurrentUserStateLocked();
993            for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
994                Service service = state.mBoundServices.get(i);
995
996                if (service.mIsDefault == isDefault) {
997                    if (canDispathEventLocked(service, event, state.mHandledFeedbackTypes)) {
998                        state.mHandledFeedbackTypes |= service.mFeedbackType;
999                        service.notifyAccessibilityEvent(event);
1000                    }
1001                }
1002            }
1003        } catch (IndexOutOfBoundsException oobe) {
1004            // An out of bounds exception can happen if services are going away
1005            // as the for loop is running. If that happens, just bail because
1006            // there are no more services to notify.
1007            return;
1008        }
1009    }
1010
1011    private void addServiceLocked(Service service, UserState userState) {
1012        try {
1013            service.linkToOwnDeathLocked();
1014            userState.mBoundServices.add(service);
1015            userState.mComponentNameToServiceMap.put(service.mComponentName, service);
1016        } catch (RemoteException re) {
1017            /* do nothing */
1018        }
1019    }
1020
1021    /**
1022     * Removes a service.
1023     *
1024     * @param service The service.
1025     * @return True if the service was removed, false otherwise.
1026     */
1027    private void removeServiceLocked(Service service, UserState userState) {
1028        userState.mBoundServices.remove(service);
1029        userState.mComponentNameToServiceMap.remove(service.mComponentName);
1030        service.unlinkToOwnDeathLocked();
1031    }
1032
1033    /**
1034     * Determines if given event can be dispatched to a service based on the package of the
1035     * event source and already notified services for that event type. Specifically, a
1036     * service is notified if it is interested in events from the package and no other service
1037     * providing the same feedback type has been notified. Exception are services the
1038     * provide generic feedback (feedback type left as a safety net for unforeseen feedback
1039     * types) which are always notified.
1040     *
1041     * @param service The potential receiver.
1042     * @param event The event.
1043     * @param handledFeedbackTypes The feedback types for which services have been notified.
1044     * @return True if the listener should be notified, false otherwise.
1045     */
1046    private boolean canDispathEventLocked(Service service, AccessibilityEvent event,
1047            int handledFeedbackTypes) {
1048
1049        if (!service.canReceiveEventsLocked()) {
1050            return false;
1051        }
1052
1053        if (!event.isImportantForAccessibility()
1054                && (service.mFetchFlags
1055                        & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
1056            return false;
1057        }
1058
1059        int eventType = event.getEventType();
1060        if ((service.mEventTypes & eventType) != eventType) {
1061            return false;
1062        }
1063
1064        Set<String> packageNames = service.mPackageNames;
1065        CharSequence packageName = event.getPackageName();
1066
1067        if (packageNames.isEmpty() || packageNames.contains(packageName)) {
1068            int feedbackType = service.mFeedbackType;
1069            if ((handledFeedbackTypes & feedbackType) != feedbackType
1070                    || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) {
1071                return true;
1072            }
1073        }
1074
1075        return false;
1076    }
1077
1078    private void unbindAllServicesLocked(UserState userState) {
1079        List<Service> services = userState.mBoundServices;
1080        for (int i = 0, count = services.size(); i < count; i++) {
1081            Service service = services.get(i);
1082            if (service.unbindLocked()) {
1083                i--;
1084                count--;
1085            }
1086        }
1087    }
1088
1089    /**
1090     * Populates a set with the {@link ComponentName}s stored in a colon
1091     * separated value setting for a given user.
1092     *
1093     * @param settingName The setting to parse.
1094     * @param userId The user id.
1095     * @param outComponentNames The output component names.
1096     */
1097    private void readComponentNamesFromSettingLocked(String settingName, int userId,
1098            Set<ComponentName> outComponentNames) {
1099        String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1100                settingName, userId);
1101        outComponentNames.clear();
1102        if (settingValue != null) {
1103            TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
1104            splitter.setString(settingValue);
1105            while (splitter.hasNext()) {
1106                String str = splitter.next();
1107                if (str == null || str.length() <= 0) {
1108                    continue;
1109                }
1110                ComponentName enabledService = ComponentName.unflattenFromString(str);
1111                if (enabledService != null) {
1112                    outComponentNames.add(enabledService);
1113                }
1114            }
1115        }
1116    }
1117
1118    /**
1119     * Persists the component names in the specified setting in a
1120     * colon separated fashion.
1121     *
1122     * @param settingName The setting name.
1123     * @param componentNames The component names.
1124     */
1125    private void persistComponentNamesToSettingLocked(String settingName,
1126            Set<ComponentName> componentNames, int userId) {
1127        StringBuilder builder = new StringBuilder();
1128        for (ComponentName componentName : componentNames) {
1129            if (builder.length() > 0) {
1130                builder.append(COMPONENT_NAME_SEPARATOR);
1131            }
1132            builder.append(componentName.flattenToShortString());
1133        }
1134        Settings.Secure.putStringForUser(mContext.getContentResolver(),
1135                settingName, builder.toString(), userId);
1136    }
1137
1138    private void manageServicesLocked(UserState userState) {
1139        Map<ComponentName, Service> componentNameToServiceMap =
1140                userState.mComponentNameToServiceMap;
1141        boolean isEnabled = userState.mIsAccessibilityEnabled;
1142
1143        for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
1144            AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
1145            ComponentName componentName = ComponentName.unflattenFromString(
1146                    installedService.getId());
1147            Service service = componentNameToServiceMap.get(componentName);
1148
1149            if (isEnabled) {
1150                // Wait for the binding if it is in process.
1151                if (userState.mBindingServices.contains(componentName)) {
1152                    continue;
1153                }
1154                if (userState.mEnabledServices.contains(componentName)) {
1155                    if (service == null) {
1156                        service = new Service(userState.mUserId, componentName, installedService);
1157                    } else if (userState.mBoundServices.contains(service)) {
1158                        continue;
1159                    }
1160                    service.bindLocked();
1161                } else {
1162                    if (service != null) {
1163                        service.unbindLocked();
1164                    }
1165                }
1166            } else {
1167                if (service != null) {
1168                    service.unbindLocked();
1169                } else {
1170                    userState.mBindingServices.remove(componentName);
1171                }
1172            }
1173        }
1174
1175        // No enabled installed services => disable accessibility to avoid
1176        // sending accessibility events with no recipient across processes.
1177        if (isEnabled && userState.mEnabledServices.isEmpty()) {
1178            userState.mIsAccessibilityEnabled = false;
1179            Settings.Secure.putIntForUser(mContext.getContentResolver(),
1180                    Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
1181        }
1182    }
1183
1184    private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
1185        final int clientState = userState.getClientState();
1186        if (userState.mLastSentClientState != clientState
1187                && (mGlobalClients.getRegisteredCallbackCount() > 0
1188                        || userState.mClients.getRegisteredCallbackCount() > 0)) {
1189            userState.mLastSentClientState = clientState;
1190            mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
1191                    clientState, userState.mUserId) .sendToTarget();
1192        }
1193    }
1194
1195    private void scheduleUpdateInputFilter(UserState userState) {
1196        mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
1197    }
1198
1199    private void updateInputFilter(UserState userState) {
1200        boolean setInputFilter = false;
1201        AccessibilityInputFilter inputFilter = null;
1202        synchronized (mLock) {
1203            int flags = 0;
1204            if (userState.mIsDisplayMagnificationEnabled) {
1205                flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
1206            }
1207            // Touch exploration without accessibility makes no sense.
1208            if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
1209                flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
1210            }
1211            if (userState.mIsFilterKeyEventsEnabled) {
1212                flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
1213            }
1214            if (flags != 0) {
1215                if (!mHasInputFilter) {
1216                    mHasInputFilter = true;
1217                    if (mInputFilter == null) {
1218                        mInputFilter = new AccessibilityInputFilter(mContext,
1219                                AccessibilityManagerService.this);
1220                    }
1221                    inputFilter = mInputFilter;
1222                    setInputFilter = true;
1223                }
1224                mInputFilter.setEnabledFeatures(flags);
1225            } else {
1226                if (mHasInputFilter) {
1227                    mHasInputFilter = false;
1228                    mInputFilter.disableFeatures();
1229                    inputFilter = null;
1230                    setInputFilter = true;
1231                }
1232            }
1233        }
1234        if (setInputFilter) {
1235            try {
1236                mWindowManagerService.setInputFilter(inputFilter);
1237            } catch (RemoteException re) {
1238                /* ignore */
1239            }
1240        }
1241    }
1242
1243    private void showEnableTouchExplorationDialog(final Service service) {
1244        synchronized (mLock) {
1245            String label = service.mResolveInfo.loadLabel(
1246            mContext.getPackageManager()).toString();
1247
1248            final UserState state = getCurrentUserStateLocked();
1249            if (state.mIsTouchExplorationEnabled) {
1250                return;
1251            }
1252            if (mEnableTouchExplorationDialog != null
1253                    && mEnableTouchExplorationDialog.isShowing()) {
1254                return;
1255            }
1256            mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
1257                .setIconAttribute(android.R.attr.alertDialogIcon)
1258                .setPositiveButton(android.R.string.ok, new OnClickListener() {
1259                     @Override
1260                     public void onClick(DialogInterface dialog, int which) {
1261                         // The user allowed the service to toggle touch exploration.
1262                         state.mTouchExplorationGrantedServices.add(service.mComponentName);
1263                         persistComponentNamesToSettingLocked(
1264                                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1265                                 state.mTouchExplorationGrantedServices, state.mUserId);
1266                         // Enable touch exploration.
1267                         UserState userState = getUserStateLocked(service.mUserId);
1268                         userState.mIsTouchExplorationEnabled = true;
1269                         Settings.Secure.putIntForUser(mContext.getContentResolver(),
1270                                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
1271                                 service.mUserId);
1272                         onUserStateChangedLocked(userState);
1273                     }
1274                 })
1275                 .setNegativeButton(android.R.string.cancel, new OnClickListener() {
1276                     @Override
1277                     public void onClick(DialogInterface dialog, int which) {
1278                         dialog.dismiss();
1279                     }
1280                 })
1281                 .setTitle(R.string.enable_explore_by_touch_warning_title)
1282                 .setMessage(mContext.getString(
1283                         R.string.enable_explore_by_touch_warning_message, label))
1284                 .create();
1285             mEnableTouchExplorationDialog.getWindow().setType(
1286                     WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1287             mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
1288                     |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
1289             mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
1290             mEnableTouchExplorationDialog.show();
1291        }
1292    }
1293
1294    private void onUserStateChangedLocked(UserState userState) {
1295        // TODO: Remove this hack
1296        mInitialized = true;
1297        updateLegacyCapabilities(userState);
1298        updateServicesLocked(userState);
1299        updateFilterKeyEventsLocked(userState);
1300        updateTouchExplorationLocked(userState);
1301        updateEnhancedWebAccessibilityLocked(userState);
1302        updateDisplayColorAdjustmentSettingsLocked(userState);
1303        scheduleUpdateInputFilter(userState);
1304        scheduleUpdateClientsIfNeededLocked(userState);
1305    }
1306
1307    private void updateLegacyCapabilities(UserState userState) {
1308        // Up to JB-MR1 we had a white list with services that can enable touch
1309        // exploration. When a service is first started we show a dialog to the
1310        // use to get a permission to white list the service.
1311        final int installedServiceCount = userState.mInstalledServices.size();
1312        for (int i = 0; i < installedServiceCount; i++) {
1313            AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
1314            ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
1315            if ((serviceInfo.getCapabilities()
1316                        & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
1317                    && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1318                        <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1319                ComponentName componentName = new ComponentName(
1320                        resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
1321                if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
1322                    serviceInfo.setCapabilities(serviceInfo.getCapabilities()
1323                            | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
1324                }
1325            }
1326        }
1327    }
1328
1329    private void updateFilterKeyEventsLocked(UserState userState) {
1330        final int serviceCount = userState.mBoundServices.size();
1331        for (int i = 0; i < serviceCount; i++) {
1332            Service service = userState.mBoundServices.get(i);
1333            if (service.mRequestFilterKeyEvents
1334                    && (service.mAccessibilityServiceInfo.getCapabilities()
1335                            & AccessibilityServiceInfo
1336                            .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
1337                userState.mIsFilterKeyEventsEnabled = true;
1338                return;
1339            }
1340        }
1341        userState.mIsFilterKeyEventsEnabled = false;
1342    }
1343
1344    private void updateServicesLocked(UserState userState) {
1345        if (userState.mIsAccessibilityEnabled) {
1346            manageServicesLocked(userState);
1347        } else {
1348            unbindAllServicesLocked(userState);
1349        }
1350    }
1351
1352    private boolean readConfigurationForUserStateLocked(UserState userState) {
1353        boolean somthingChanged = false;
1354        somthingChanged |= readAccessibilityEnabledSettingLocked(userState);
1355        somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
1356        somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
1357        somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
1358        somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
1359        somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
1360        somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
1361        somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
1362        return somthingChanged;
1363    }
1364
1365    private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
1366        final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
1367               mContext.getContentResolver(),
1368               Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
1369        if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
1370            userState.mIsAccessibilityEnabled = accessibilityEnabled;
1371            return true;
1372        }
1373        return false;
1374    }
1375
1376    private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
1377        final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
1378                mContext.getContentResolver(),
1379                Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
1380        if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
1381            userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
1382            return true;
1383        }
1384        return false;
1385    }
1386
1387    private boolean readDisplayMagnificationEnabledSettingLocked(UserState userState) {
1388        final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
1389                mContext.getContentResolver(),
1390                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
1391                0, userState.mUserId) == 1;
1392        if (displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) {
1393            userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
1394            return true;
1395        }
1396        return false;
1397    }
1398
1399    private boolean readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) {
1400         final boolean enhancedWeAccessibilityEnabled = Settings.Secure.getIntForUser(
1401                mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
1402                0, userState.mUserId) == 1;
1403         if (enhancedWeAccessibilityEnabled != userState.mIsEnhancedWebAccessibilityEnabled) {
1404             userState.mIsEnhancedWebAccessibilityEnabled = enhancedWeAccessibilityEnabled;
1405             return true;
1406         }
1407         return false;
1408    }
1409
1410    private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) {
1411        final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext,
1412                userState.mUserId);
1413        if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) {
1414            userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled;
1415            return true;
1416        }
1417        // If display adjustment is enabled, always assume there was a change in
1418        // the adjustment settings.
1419        return displayAdjustmentsEnabled;
1420    }
1421
1422    private void updateTouchExplorationLocked(UserState userState) {
1423        boolean enabled = false;
1424        final int serviceCount = userState.mBoundServices.size();
1425        for (int i = 0; i < serviceCount; i++) {
1426            Service service = userState.mBoundServices.get(i);
1427            if (canRequestAndRequestsTouchExplorationLocked(service)) {
1428                enabled = true;
1429                break;
1430            }
1431        }
1432        if (enabled != userState.mIsTouchExplorationEnabled) {
1433            userState.mIsTouchExplorationEnabled = enabled;
1434            Settings.Secure.putIntForUser(mContext.getContentResolver(),
1435                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
1436                    userState.mUserId);
1437        }
1438        try {
1439            mWindowManagerService.setTouchExplorationEnabled(enabled);
1440        } catch (RemoteException e) {
1441            e.printStackTrace();
1442        }
1443    }
1444
1445    private boolean canRequestAndRequestsTouchExplorationLocked(Service service) {
1446        // Service not ready or cannot request the feature - well nothing to do.
1447        if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
1448            return false;
1449        }
1450        // UI test automation service can always enable it.
1451        if (service.mIsAutomation) {
1452            return true;
1453        }
1454        if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1455                <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1456            // Up to JB-MR1 we had a white list with services that can enable touch
1457            // exploration. When a service is first started we show a dialog to the
1458            // use to get a permission to white list the service.
1459            UserState userState = getUserStateLocked(service.mUserId);
1460            if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
1461                return true;
1462            } else if (mEnableTouchExplorationDialog == null
1463                    || !mEnableTouchExplorationDialog.isShowing()) {
1464                mMainHandler.obtainMessage(
1465                        MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG,
1466                        service).sendToTarget();
1467            }
1468        } else {
1469            // Starting in JB-MR2 we request an accessibility service to declare
1470            // certain capabilities in its meta-data to allow it to enable the
1471            // corresponding features.
1472            if ((service.mAccessibilityServiceInfo.getCapabilities()
1473                    & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
1474                return true;
1475            }
1476        }
1477        return false;
1478    }
1479
1480    private void updateEnhancedWebAccessibilityLocked(UserState userState) {
1481        boolean enabled = false;
1482        final int serviceCount = userState.mBoundServices.size();
1483        for (int i = 0; i < serviceCount; i++) {
1484            Service service = userState.mBoundServices.get(i);
1485            if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) {
1486                enabled = true;
1487                break;
1488            }
1489        }
1490        if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) {
1491            userState.mIsEnhancedWebAccessibilityEnabled = enabled;
1492            Settings.Secure.putIntForUser(mContext.getContentResolver(),
1493                    Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0,
1494                    userState.mUserId);
1495        }
1496    }
1497
1498    private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) {
1499        if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
1500            return false;
1501        }
1502        if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities()
1503               & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) {
1504            return true;
1505        }
1506        return false;
1507    }
1508
1509    private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) {
1510        DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
1511    }
1512
1513    @Override
1514    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1515        mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
1516        synchronized (mLock) {
1517            pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
1518            pw.println();
1519            final int userCount = mUserStates.size();
1520            for (int i = 0; i < userCount; i++) {
1521                UserState userState = mUserStates.valueAt(i);
1522                pw.append("User state[attributes:{id=" + userState.mUserId);
1523                pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
1524                pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
1525                pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
1526                pw.append(", displayMagnificationEnabled="
1527                        + userState.mIsDisplayMagnificationEnabled);
1528                if (userState.mUiAutomationService != null) {
1529                    pw.append(", ");
1530                    userState.mUiAutomationService.dump(fd, pw, args);
1531                    pw.println();
1532                }
1533                pw.append("}");
1534                pw.println();
1535                pw.append("           services:{");
1536                final int serviceCount = userState.mBoundServices.size();
1537                for (int j = 0; j < serviceCount; j++) {
1538                    if (j > 0) {
1539                        pw.append(", ");
1540                        pw.println();
1541                        pw.append("                     ");
1542                    }
1543                    Service service = userState.mBoundServices.get(j);
1544                    service.dump(fd, pw, args);
1545                }
1546                pw.println("}]");
1547                pw.println();
1548            }
1549        }
1550    }
1551
1552    private class AccessibilityConnectionWrapper implements DeathRecipient {
1553        private final int mWindowId;
1554        private final int mUserId;
1555        private final IAccessibilityInteractionConnection mConnection;
1556
1557        public AccessibilityConnectionWrapper(int windowId,
1558                IAccessibilityInteractionConnection connection, int userId) {
1559            mWindowId = windowId;
1560            mUserId = userId;
1561            mConnection = connection;
1562        }
1563
1564        public void linkToDeath() throws RemoteException {
1565            mConnection.asBinder().linkToDeath(this, 0);
1566        }
1567
1568        public void unlinkToDeath() {
1569            mConnection.asBinder().unlinkToDeath(this, 0);
1570        }
1571
1572        @Override
1573        public void binderDied() {
1574            unlinkToDeath();
1575            synchronized (mLock) {
1576                removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
1577            }
1578        }
1579    }
1580
1581    private final class MainHandler extends Handler {
1582        public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
1583        public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
1584        public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
1585        public static final int MSG_UPDATE_ACTIVE_WINDOW = 4;
1586        public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
1587        public static final int MSG_UPDATE_INPUT_FILTER = 6;
1588        public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
1589        public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
1590
1591        public MainHandler(Looper looper) {
1592            super(looper);
1593        }
1594
1595        @Override
1596        public void handleMessage(Message msg) {
1597            final int type = msg.what;
1598            switch (type) {
1599                case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
1600                    AccessibilityEvent event = (AccessibilityEvent) msg.obj;
1601                    synchronized (mLock) {
1602                        if (mHasInputFilter && mInputFilter != null) {
1603                            mInputFilter.notifyAccessibilityEvent(event);
1604                        }
1605                    }
1606                    event.recycle();
1607                } break;
1608                case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: {
1609                    KeyEvent event = (KeyEvent) msg.obj;
1610                    final int policyFlags = msg.arg1;
1611                    synchronized (mLock) {
1612                        if (mHasInputFilter && mInputFilter != null) {
1613                            mInputFilter.sendInputEvent(event, policyFlags);
1614                        }
1615                    }
1616                    event.recycle();
1617                } break;
1618                case MSG_SEND_STATE_TO_CLIENTS: {
1619                    final int clientState = msg.arg1;
1620                    final int userId = msg.arg2;
1621                    sendStateToClients(clientState, mGlobalClients);
1622                    sendStateToClientsForUser(clientState, userId);
1623                } break;
1624                case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
1625                    final int userId = msg.arg1;
1626                    sendStateToClientsForUser(0, userId);
1627                } break;
1628                case MSG_UPDATE_ACTIVE_WINDOW: {
1629                    final int windowId = msg.arg1;
1630                    final int eventType = msg.arg2;
1631                    mSecurityPolicy.updateActiveWindow(windowId, eventType);
1632                } break;
1633                case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
1634                    announceNewUserIfNeeded();
1635                } break;
1636                case MSG_UPDATE_INPUT_FILTER: {
1637                    UserState userState = (UserState) msg.obj;
1638                    updateInputFilter(userState);
1639                } break;
1640                case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: {
1641                    Service service = (Service) msg.obj;
1642                    showEnableTouchExplorationDialog(service);
1643                } break;
1644            }
1645        }
1646
1647        private void announceNewUserIfNeeded() {
1648            synchronized (mLock) {
1649                UserState userState = getCurrentUserStateLocked();
1650                if (userState.mIsAccessibilityEnabled) {
1651                    UserManager userManager = (UserManager) mContext.getSystemService(
1652                            Context.USER_SERVICE);
1653                    String message = mContext.getString(R.string.user_switched,
1654                            userManager.getUserInfo(mCurrentUserId).name);
1655                    AccessibilityEvent event = AccessibilityEvent.obtain(
1656                            AccessibilityEvent.TYPE_ANNOUNCEMENT);
1657                    event.getText().add(message);
1658                    event.setWindowId(mSecurityPolicy.getRetrievalAllowingWindowLocked());
1659                    sendAccessibilityEvent(event, mCurrentUserId);
1660                }
1661            }
1662        }
1663
1664        private void sendStateToClientsForUser(int clientState, int userId) {
1665            final UserState userState;
1666            synchronized (mLock) {
1667                userState = getUserStateLocked(userId);
1668            }
1669            sendStateToClients(clientState, userState.mClients);
1670        }
1671
1672        private void sendStateToClients(int clientState,
1673                RemoteCallbackList<IAccessibilityManagerClient> clients) {
1674            try {
1675                final int userClientCount = clients.beginBroadcast();
1676                for (int i = 0; i < userClientCount; i++) {
1677                    IAccessibilityManagerClient client = clients.getBroadcastItem(i);
1678                    try {
1679                        client.setState(clientState);
1680                    } catch (RemoteException re) {
1681                        /* ignore */
1682                    }
1683                }
1684            } finally {
1685                clients.finishBroadcast();
1686            }
1687        }
1688    }
1689
1690    private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) {
1691        PendingEvent pendingEvent = mPendingEventPool.acquire();
1692        if (pendingEvent == null) {
1693            pendingEvent = new PendingEvent();
1694        }
1695        pendingEvent.event = event;
1696        pendingEvent.policyFlags = policyFlags;
1697        pendingEvent.sequence = sequence;
1698        return pendingEvent;
1699    }
1700
1701    private void recyclePendingEventLocked(PendingEvent pendingEvent) {
1702        pendingEvent.clear();
1703        mPendingEventPool.release(pendingEvent);
1704    }
1705
1706    /**
1707     * This class represents an accessibility service. It stores all per service
1708     * data required for the service management, provides API for starting/stopping the
1709     * service and is responsible for adding/removing the service in the data structures
1710     * for service management. The class also exposes configuration interface that is
1711     * passed to the service it represents as soon it is bound. It also serves as the
1712     * connection for the service.
1713     */
1714    class Service extends IAccessibilityServiceConnection.Stub
1715            implements ServiceConnection, DeathRecipient {;
1716
1717        final int mUserId;
1718
1719        int mId = 0;
1720
1721        AccessibilityServiceInfo mAccessibilityServiceInfo;
1722
1723        IBinder mService;
1724
1725        IAccessibilityServiceClient mServiceInterface;
1726
1727        int mEventTypes;
1728
1729        int mFeedbackType;
1730
1731        Set<String> mPackageNames = new HashSet<String>();
1732
1733        boolean mIsDefault;
1734
1735        boolean mRequestTouchExplorationMode;
1736
1737        boolean mRequestEnhancedWebAccessibility;
1738
1739        boolean mRequestFilterKeyEvents;
1740
1741        int mFetchFlags;
1742
1743        long mNotificationTimeout;
1744
1745        ComponentName mComponentName;
1746
1747        Intent mIntent;
1748
1749        boolean mIsAutomation;
1750
1751        final Rect mTempBounds = new Rect();
1752
1753        final ResolveInfo mResolveInfo;
1754
1755        // the events pending events to be dispatched to this service
1756        final SparseArray<AccessibilityEvent> mPendingEvents =
1757            new SparseArray<AccessibilityEvent>();
1758
1759        final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher();
1760
1761        boolean mWasConnectedAndDied;
1762
1763        // Handler only for dispatching accessibility events since we use event
1764        // types as message types allowing us to remove messages per event type.
1765        public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
1766            @Override
1767            public void handleMessage(Message message) {
1768                final int eventType =  message.what;
1769                notifyAccessibilityEventInternal(eventType);
1770            }
1771        };
1772
1773        // Handler for scheduling method invocations on the main thread.
1774        public InvocationHandler mInvocationHandler = new InvocationHandler(
1775                mMainHandler.getLooper());
1776
1777        public Service(int userId, ComponentName componentName,
1778                AccessibilityServiceInfo accessibilityServiceInfo) {
1779            mUserId = userId;
1780            mResolveInfo = accessibilityServiceInfo.getResolveInfo();
1781            mId = sIdCounter++;
1782            mComponentName = componentName;
1783            mAccessibilityServiceInfo = accessibilityServiceInfo;
1784            mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
1785            if (!mIsAutomation) {
1786                mIntent = new Intent().setComponent(mComponentName);
1787                mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1788                        com.android.internal.R.string.accessibility_binding_label);
1789                mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1790                        mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
1791            }
1792            setDynamicallyConfigurableProperties(accessibilityServiceInfo);
1793        }
1794
1795        public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
1796            mEventTypes = info.eventTypes;
1797            mFeedbackType = info.feedbackType;
1798            String[] packageNames = info.packageNames;
1799            if (packageNames != null) {
1800                mPackageNames.addAll(Arrays.asList(packageNames));
1801            }
1802            mNotificationTimeout = info.notificationTimeout;
1803            mIsDefault = (info.flags & DEFAULT) != 0;
1804
1805            if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
1806                    >= Build.VERSION_CODES.JELLY_BEAN) {
1807                if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
1808                    mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
1809                } else {
1810                    mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
1811                }
1812            }
1813
1814            if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
1815                mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
1816            } else {
1817                mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
1818            }
1819
1820            mRequestTouchExplorationMode = (info.flags
1821                    & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
1822            mRequestEnhancedWebAccessibility = (info.flags
1823                    & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
1824            mRequestFilterKeyEvents = (info.flags
1825                    & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS)  != 0;
1826        }
1827
1828        /**
1829         * Binds to the accessibility service.
1830         *
1831         * @return True if binding is successful.
1832         */
1833        public boolean bindLocked() {
1834            UserState userState = getUserStateLocked(mUserId);
1835            if (!mIsAutomation) {
1836                if (mService == null && mContext.bindServiceAsUser(
1837                        mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) {
1838                    userState.mBindingServices.add(mComponentName);
1839                }
1840            } else {
1841                userState.mBindingServices.add(mComponentName);
1842                mService = userState.mUiAutomationServiceClient.asBinder();
1843                onServiceConnected(mComponentName, mService);
1844                userState.mUiAutomationService = this;
1845            }
1846            return false;
1847        }
1848
1849        /**
1850         * Unbinds form the accessibility service and removes it from the data
1851         * structures for service management.
1852         *
1853         * @return True if unbinding is successful.
1854         */
1855        public boolean unbindLocked() {
1856            if (mService == null) {
1857                return false;
1858            }
1859            UserState userState = getUserStateLocked(mUserId);
1860            mKeyEventDispatcher.flush();
1861            if (!mIsAutomation) {
1862                mContext.unbindService(this);
1863            } else {
1864                userState.destroyUiAutomationService();
1865            }
1866            removeServiceLocked(this, userState);
1867            resetLocked();
1868            return true;
1869        }
1870
1871        public boolean canReceiveEventsLocked() {
1872            return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
1873        }
1874
1875        @Override
1876        public void setOnKeyEventResult(boolean handled, int sequence) {
1877            mKeyEventDispatcher.setOnKeyEventResult(handled, sequence);
1878        }
1879
1880        @Override
1881        public AccessibilityServiceInfo getServiceInfo() {
1882            synchronized (mLock) {
1883                return mAccessibilityServiceInfo;
1884            }
1885        }
1886
1887        @Override
1888        public void setServiceInfo(AccessibilityServiceInfo info) {
1889            final long identity = Binder.clearCallingIdentity();
1890            try {
1891                synchronized (mLock) {
1892                    // If the XML manifest had data to configure the service its info
1893                    // should be already set. In such a case update only the dynamically
1894                    // configurable properties.
1895                    AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
1896                    if (oldInfo != null) {
1897                        oldInfo.updateDynamicallyConfigurableProperties(info);
1898                        setDynamicallyConfigurableProperties(oldInfo);
1899                    } else {
1900                        setDynamicallyConfigurableProperties(info);
1901                    }
1902                    UserState userState = getUserStateLocked(mUserId);
1903                    onUserStateChangedLocked(userState);
1904                }
1905            } finally {
1906                Binder.restoreCallingIdentity(identity);
1907            }
1908        }
1909
1910        @Override
1911        public void onServiceConnected(ComponentName componentName, IBinder service) {
1912            synchronized (mLock) {
1913                mService = service;
1914                mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
1915                UserState userState = getUserStateLocked(mUserId);
1916                addServiceLocked(this, userState);
1917                if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
1918                    userState.mBindingServices.remove(mComponentName);
1919                    mWasConnectedAndDied = false;
1920                    try {
1921                       mServiceInterface.setConnection(this, mId);
1922                       onUserStateChangedLocked(userState);
1923                    } catch (RemoteException re) {
1924                        Slog.w(LOG_TAG, "Error while setting connection for service: "
1925                                + service, re);
1926                        binderDied();
1927                    }
1928                } else {
1929                    binderDied();
1930                }
1931            }
1932        }
1933
1934        @Override
1935        public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
1936                long accessibilityNodeId, String viewIdResName, int interactionId,
1937                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
1938                throws RemoteException {
1939            final int resolvedWindowId;
1940            IAccessibilityInteractionConnection connection = null;
1941            synchronized (mLock) {
1942                final int resolvedUserId = mSecurityPolicy
1943                        .resolveCallingUserIdEnforcingPermissionsLocked(
1944                                UserHandle.getCallingUserId());
1945                if (resolvedUserId != mCurrentUserId) {
1946                    return false;
1947                }
1948                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
1949                final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
1950                if (!permissionGranted) {
1951                    return false;
1952                } else {
1953                    resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
1954                    connection = getConnectionLocked(resolvedWindowId);
1955                    if (connection == null) {
1956                        return false;
1957                    }
1958                }
1959            }
1960            final int interrogatingPid = Binder.getCallingPid();
1961            final long identityToken = Binder.clearCallingIdentity();
1962            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
1963            try {
1964                connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
1965                        viewIdResName, interactionId, callback, mFetchFlags, interrogatingPid,
1966                        interrogatingTid, spec);
1967                return true;
1968            } catch (RemoteException re) {
1969                if (DEBUG) {
1970                    Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
1971                }
1972            } finally {
1973                Binder.restoreCallingIdentity(identityToken);
1974            }
1975            return false;
1976        }
1977
1978        @Override
1979        public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
1980                long accessibilityNodeId, String text, int interactionId,
1981                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
1982                throws RemoteException {
1983            final int resolvedWindowId;
1984            IAccessibilityInteractionConnection connection = null;
1985            synchronized (mLock) {
1986                final int resolvedUserId = mSecurityPolicy
1987                        .resolveCallingUserIdEnforcingPermissionsLocked(
1988                        UserHandle.getCallingUserId());
1989                if (resolvedUserId != mCurrentUserId) {
1990                    return false;
1991                }
1992                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
1993                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
1994                final boolean permissionGranted =
1995                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
1996                if (!permissionGranted) {
1997                    return false;
1998                } else {
1999                    connection = getConnectionLocked(resolvedWindowId);
2000                    if (connection == null) {
2001                        return false;
2002                    }
2003                }
2004            }
2005            final int interrogatingPid = Binder.getCallingPid();
2006            final long identityToken = Binder.clearCallingIdentity();
2007            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
2008            try {
2009                connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
2010                        interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
2011                        spec);
2012                return true;
2013            } catch (RemoteException re) {
2014                if (DEBUG) {
2015                    Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
2016                }
2017            } finally {
2018                Binder.restoreCallingIdentity(identityToken);
2019            }
2020            return false;
2021        }
2022
2023        @Override
2024        public boolean findAccessibilityNodeInfoByAccessibilityId(
2025                int accessibilityWindowId, long accessibilityNodeId, int interactionId,
2026                IAccessibilityInteractionConnectionCallback callback, int flags,
2027                long interrogatingTid) throws RemoteException {
2028            final int resolvedWindowId;
2029            IAccessibilityInteractionConnection connection = null;
2030            synchronized (mLock) {
2031                final int resolvedUserId = mSecurityPolicy
2032                        .resolveCallingUserIdEnforcingPermissionsLocked(
2033                        UserHandle.getCallingUserId());
2034                if (resolvedUserId != mCurrentUserId) {
2035                    return false;
2036                }
2037                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
2038                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2039                final boolean permissionGranted =
2040                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2041                if (!permissionGranted) {
2042                    return false;
2043                } else {
2044                    connection = getConnectionLocked(resolvedWindowId);
2045                    if (connection == null) {
2046                        return false;
2047                    }
2048                }
2049            }
2050            final int interrogatingPid = Binder.getCallingPid();
2051            final long identityToken = Binder.clearCallingIdentity();
2052            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
2053            try {
2054                connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
2055                        interactionId, callback, mFetchFlags | flags, interrogatingPid,
2056                        interrogatingTid, spec);
2057                return true;
2058            } catch (RemoteException re) {
2059                if (DEBUG) {
2060                    Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
2061                }
2062            } finally {
2063                Binder.restoreCallingIdentity(identityToken);
2064            }
2065            return false;
2066        }
2067
2068        @Override
2069        public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
2070                int focusType, int interactionId,
2071                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2072                throws RemoteException {
2073            final int resolvedWindowId;
2074            IAccessibilityInteractionConnection connection = null;
2075            synchronized (mLock) {
2076                final int resolvedUserId = mSecurityPolicy
2077                        .resolveCallingUserIdEnforcingPermissionsLocked(
2078                        UserHandle.getCallingUserId());
2079                if (resolvedUserId != mCurrentUserId) {
2080                    return false;
2081                }
2082                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
2083                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2084                final boolean permissionGranted =
2085                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2086                if (!permissionGranted) {
2087                    return false;
2088                } else {
2089                    connection = getConnectionLocked(resolvedWindowId);
2090                    if (connection == null) {
2091                        return false;
2092                    }
2093                }
2094            }
2095            final int interrogatingPid = Binder.getCallingPid();
2096            final long identityToken = Binder.clearCallingIdentity();
2097            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
2098            try {
2099                connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
2100                        mFetchFlags, interrogatingPid, interrogatingTid, spec);
2101                return true;
2102            } catch (RemoteException re) {
2103                if (DEBUG) {
2104                    Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
2105                }
2106            } finally {
2107                Binder.restoreCallingIdentity(identityToken);
2108            }
2109            return false;
2110        }
2111
2112        @Override
2113        public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
2114                int direction, int interactionId,
2115                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2116                throws RemoteException {
2117            final int resolvedWindowId;
2118            IAccessibilityInteractionConnection connection = null;
2119            synchronized (mLock) {
2120                final int resolvedUserId = mSecurityPolicy
2121                        .resolveCallingUserIdEnforcingPermissionsLocked(
2122                        UserHandle.getCallingUserId());
2123                if (resolvedUserId != mCurrentUserId) {
2124                    return false;
2125                }
2126                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
2127                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2128                final boolean permissionGranted =
2129                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2130                if (!permissionGranted) {
2131                    return false;
2132                } else {
2133                    connection = getConnectionLocked(resolvedWindowId);
2134                    if (connection == null) {
2135                        return false;
2136                    }
2137                }
2138            }
2139            final int interrogatingPid = Binder.getCallingPid();
2140            final long identityToken = Binder.clearCallingIdentity();
2141            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
2142            try {
2143                connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
2144                        mFetchFlags, interrogatingPid, interrogatingTid, spec);
2145                return true;
2146            } catch (RemoteException re) {
2147                if (DEBUG) {
2148                    Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
2149                }
2150            } finally {
2151                Binder.restoreCallingIdentity(identityToken);
2152            }
2153            return false;
2154        }
2155
2156        @Override
2157        public boolean performAccessibilityAction(int accessibilityWindowId,
2158                long accessibilityNodeId, int action, Bundle arguments, int interactionId,
2159                IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2160                throws RemoteException {
2161            final int resolvedWindowId;
2162            IAccessibilityInteractionConnection connection = null;
2163            synchronized (mLock) {
2164                final int resolvedUserId = mSecurityPolicy
2165                        .resolveCallingUserIdEnforcingPermissionsLocked(
2166                        UserHandle.getCallingUserId());
2167                if (resolvedUserId != mCurrentUserId) {
2168                    return false;
2169                }
2170                mSecurityPolicy.enforceCanRetrieveWindowContent(this);
2171                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2172                final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
2173                        resolvedWindowId, action, arguments);
2174                if (!permissionGranted) {
2175                    return false;
2176                } else {
2177                    connection = getConnectionLocked(resolvedWindowId);
2178                    if (connection == null) {
2179                        return false;
2180                    }
2181                }
2182            }
2183            final int interrogatingPid = Binder.getCallingPid();
2184            final long identityToken = Binder.clearCallingIdentity();
2185            try {
2186                connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
2187                        interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
2188            } catch (RemoteException re) {
2189                if (DEBUG) {
2190                    Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
2191                }
2192            } finally {
2193                Binder.restoreCallingIdentity(identityToken);
2194            }
2195            return true;
2196        }
2197
2198        public boolean performGlobalAction(int action) {
2199            synchronized (mLock) {
2200                final int resolvedUserId = mSecurityPolicy
2201                        .resolveCallingUserIdEnforcingPermissionsLocked(
2202                        UserHandle.getCallingUserId());
2203                if (resolvedUserId != mCurrentUserId) {
2204                    return false;
2205                }
2206            }
2207            final long identity = Binder.clearCallingIdentity();
2208            try {
2209                switch (action) {
2210                    case AccessibilityService.GLOBAL_ACTION_BACK: {
2211                        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
2212                    } return true;
2213                    case AccessibilityService.GLOBAL_ACTION_HOME: {
2214                        sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
2215                    } return true;
2216                    case AccessibilityService.GLOBAL_ACTION_RECENTS: {
2217                        openRecents();
2218                    } return true;
2219                    case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
2220                        expandNotifications();
2221                    } return true;
2222                    case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
2223                        expandQuickSettings();
2224                    } return true;
2225                }
2226                return false;
2227            } finally {
2228                Binder.restoreCallingIdentity(identity);
2229            }
2230        }
2231
2232        @Override
2233        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2234            mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
2235            synchronized (mLock) {
2236                pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
2237                        .loadLabel(mContext.getPackageManager()));
2238                pw.append(", feedbackType"
2239                        + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
2240                pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
2241                pw.append(", eventTypes="
2242                        + AccessibilityEvent.eventTypeToString(mEventTypes));
2243                pw.append(", notificationTimeout=" + mNotificationTimeout);
2244                pw.append("]");
2245            }
2246        }
2247
2248        @Override
2249        public void onServiceDisconnected(ComponentName componentName) {
2250            /* do nothing - #binderDied takes care */
2251        }
2252
2253        public void linkToOwnDeathLocked() throws RemoteException {
2254            mService.linkToDeath(this, 0);
2255        }
2256
2257        public void unlinkToOwnDeathLocked() {
2258            mService.unlinkToDeath(this, 0);
2259        }
2260
2261        public void resetLocked() {
2262            try {
2263                // Clear the proxy in the other process so this
2264                // IAccessibilityServiceConnection can be garbage collected.
2265                mServiceInterface.setConnection(null, mId);
2266            } catch (RemoteException re) {
2267                /* ignore */
2268            }
2269            mService = null;
2270            mServiceInterface = null;
2271        }
2272
2273        public boolean isConnectedLocked() {
2274            return (mService != null);
2275        }
2276
2277        public void binderDied() {
2278            synchronized (mLock) {
2279                // It is possible that this service's package was force stopped during
2280                // whose handling the death recipient is unlinked and still get a call
2281                // on binderDied since the call was made before we unlink but was
2282                // waiting on the lock we held during the force stop handling.
2283                if (!isConnectedLocked()) {
2284                    return;
2285                }
2286                mWasConnectedAndDied = true;
2287                mKeyEventDispatcher.flush();
2288                UserState userState = getUserStateLocked(mUserId);
2289                // The death recipient is unregistered in removeServiceLocked
2290                removeServiceLocked(this, userState);
2291                resetLocked();
2292                if (mIsAutomation) {
2293                    // We no longer have an automation service, so restore
2294                    // the state based on values in the settings database.
2295                    userState.mInstalledServices.remove(mAccessibilityServiceInfo);
2296                    userState.mEnabledServices.remove(mComponentName);
2297                    userState.destroyUiAutomationService();
2298                }
2299            }
2300        }
2301
2302        /**
2303         * Performs a notification for an {@link AccessibilityEvent}.
2304         *
2305         * @param event The event.
2306         */
2307        public void notifyAccessibilityEvent(AccessibilityEvent event) {
2308            synchronized (mLock) {
2309                final int eventType = event.getEventType();
2310                // Make a copy since during dispatch it is possible the event to
2311                // be modified to remove its source if the receiving service does
2312                // not have permission to access the window content.
2313                AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
2314                AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
2315                mPendingEvents.put(eventType, newEvent);
2316
2317                final int what = eventType;
2318                if (oldEvent != null) {
2319                    mEventDispatchHandler.removeMessages(what);
2320                    oldEvent.recycle();
2321                }
2322
2323                Message message = mEventDispatchHandler.obtainMessage(what);
2324                mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
2325            }
2326        }
2327
2328        /**
2329         * Notifies an accessibility service client for a scheduled event given the event type.
2330         *
2331         * @param eventType The type of the event to dispatch.
2332         */
2333        private void notifyAccessibilityEventInternal(int eventType) {
2334            IAccessibilityServiceClient listener;
2335            AccessibilityEvent event;
2336
2337            synchronized (mLock) {
2338                listener = mServiceInterface;
2339
2340                // If the service died/was disabled while the message for dispatching
2341                // the accessibility event was propagating the listener may be null.
2342                if (listener == null) {
2343                    return;
2344                }
2345
2346                event = mPendingEvents.get(eventType);
2347
2348                // Check for null here because there is a concurrent scenario in which this
2349                // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
2350                // which posts a message for dispatching an event. 2) The message is pulled
2351                // from the queue by the handler on the service thread and the latter is
2352                // just about to acquire the lock and call this method. 3) Now another binder
2353                // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
2354                // so the service thread waits for the lock; 4) The binder thread replaces
2355                // the event with a more recent one (assume the same event type) and posts a
2356                // dispatch request releasing the lock. 5) Now the main thread is unblocked and
2357                // dispatches the event which is removed from the pending ones. 6) And ... now
2358                // the service thread handles the last message posted by the last binder call
2359                // but the event is already dispatched and hence looking it up in the pending
2360                // ones yields null. This check is much simpler that keeping count for each
2361                // event type of each service to catch such a scenario since only one message
2362                // is processed at a time.
2363                if (event == null) {
2364                    return;
2365                }
2366
2367                mPendingEvents.remove(eventType);
2368                if (mSecurityPolicy.canRetrieveWindowContent(this)) {
2369                    event.setConnectionId(mId);
2370                } else {
2371                    event.setSource(null);
2372                }
2373                event.setSealed(true);
2374            }
2375
2376            try {
2377                listener.onAccessibilityEvent(event);
2378                if (DEBUG) {
2379                    Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
2380                }
2381            } catch (RemoteException re) {
2382                Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
2383            } finally {
2384                event.recycle();
2385            }
2386        }
2387
2388        public void notifyGesture(int gestureId) {
2389            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
2390                    gestureId, 0).sendToTarget();
2391        }
2392
2393        public void notifyKeyEvent(KeyEvent event, int policyFlags) {
2394            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT,
2395                    policyFlags, 0, event).sendToTarget();
2396        }
2397
2398        public void notifyClearAccessibilityNodeInfoCache() {
2399            mInvocationHandler.sendEmptyMessage(
2400                    InvocationHandler.MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE);
2401        }
2402
2403        private void notifyGestureInternal(int gestureId) {
2404            IAccessibilityServiceClient listener = mServiceInterface;
2405            if (listener != null) {
2406                try {
2407                    listener.onGesture(gestureId);
2408                } catch (RemoteException re) {
2409                    Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
2410                            + " to " + mService, re);
2411                }
2412            }
2413        }
2414
2415        private void notifyKeyEventInternal(KeyEvent event, int policyFlags) {
2416            mKeyEventDispatcher.notifyKeyEvent(event, policyFlags);
2417        }
2418
2419        private void notifyClearAccessibilityNodeInfoCacheInternal() {
2420            IAccessibilityServiceClient listener = mServiceInterface;
2421            if (listener != null) {
2422                try {
2423                    listener.clearAccessibilityNodeInfoCache();
2424                } catch (RemoteException re) {
2425                    Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
2426                            + " to be cleared.", re);
2427                }
2428            }
2429        }
2430
2431        private void sendDownAndUpKeyEvents(int keyCode) {
2432            final long token = Binder.clearCallingIdentity();
2433
2434            // Inject down.
2435            final long downTime = SystemClock.uptimeMillis();
2436            KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
2437                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
2438                    InputDevice.SOURCE_KEYBOARD, null);
2439            InputManager.getInstance().injectInputEvent(down,
2440                    InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
2441            down.recycle();
2442
2443            // Inject up.
2444            final long upTime = SystemClock.uptimeMillis();
2445            KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
2446                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
2447                    InputDevice.SOURCE_KEYBOARD, null);
2448            InputManager.getInstance().injectInputEvent(up,
2449                    InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
2450            up.recycle();
2451
2452            Binder.restoreCallingIdentity(token);
2453        }
2454
2455        private void expandNotifications() {
2456            final long token = Binder.clearCallingIdentity();
2457
2458            StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
2459                    android.app.Service.STATUS_BAR_SERVICE);
2460            statusBarManager.expandNotificationsPanel();
2461
2462            Binder.restoreCallingIdentity(token);
2463        }
2464
2465        private void expandQuickSettings() {
2466            final long token = Binder.clearCallingIdentity();
2467
2468            StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
2469                    android.app.Service.STATUS_BAR_SERVICE);
2470            statusBarManager.expandSettingsPanel();
2471
2472            Binder.restoreCallingIdentity(token);
2473        }
2474
2475        private void openRecents() {
2476            final long token = Binder.clearCallingIdentity();
2477
2478            IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
2479                    ServiceManager.getService("statusbar"));
2480            try {
2481                statusBarService.toggleRecentApps();
2482            } catch (RemoteException e) {
2483                Slog.e(LOG_TAG, "Error toggling recent apps.");
2484            }
2485
2486            Binder.restoreCallingIdentity(token);
2487        }
2488
2489        private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
2490            if (DEBUG) {
2491                Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
2492            }
2493            AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
2494            if (wrapper == null) {
2495                wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
2496            }
2497            if (wrapper != null && wrapper.mConnection != null) {
2498                return wrapper.mConnection;
2499            }
2500            if (DEBUG) {
2501                Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
2502            }
2503            return null;
2504        }
2505
2506        private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
2507            if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
2508                return mSecurityPolicy.mActiveWindowId;
2509            }
2510            return accessibilityWindowId;
2511        }
2512
2513        private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
2514            try {
2515                IBinder windowToken = mGlobalWindowTokens.get(windowId);
2516                if (windowToken == null) {
2517                    windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
2518                }
2519                if (windowToken != null) {
2520                    return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
2521                            windowToken);
2522                }
2523            } catch (RemoteException re) {
2524                /* ignore */
2525            }
2526            return null;
2527        }
2528
2529        private final class InvocationHandler extends Handler {
2530
2531            public static final int MSG_ON_GESTURE = 1;
2532            public static final int MSG_ON_KEY_EVENT = 2;
2533            public static final int MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 3;
2534            public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4;
2535
2536            public InvocationHandler(Looper looper) {
2537                super(looper, null, true);
2538            }
2539
2540            @Override
2541            public void handleMessage(Message message) {
2542                final int type = message.what;
2543                switch (type) {
2544                    case MSG_ON_GESTURE: {
2545                        final int gestureId = message.arg1;
2546                        notifyGestureInternal(gestureId);
2547                    } break;
2548                    case MSG_ON_KEY_EVENT: {
2549                        KeyEvent event = (KeyEvent) message.obj;
2550                        final int policyFlags = message.arg1;
2551                        notifyKeyEventInternal(event, policyFlags);
2552                    } break;
2553                    case MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE: {
2554                        notifyClearAccessibilityNodeInfoCacheInternal();
2555                    } break;
2556                    case MSG_ON_KEY_EVENT_TIMEOUT: {
2557                        PendingEvent eventState = (PendingEvent) message.obj;
2558                        setOnKeyEventResult(false, eventState.sequence);
2559                    } break;
2560                    default: {
2561                        throw new IllegalArgumentException("Unknown message: " + type);
2562                    }
2563                }
2564            }
2565        }
2566
2567        private final class KeyEventDispatcher {
2568
2569            private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500;
2570
2571            private PendingEvent mPendingEvents;
2572
2573            private final InputEventConsistencyVerifier mSentEventsVerifier =
2574                    InputEventConsistencyVerifier.isInstrumentationEnabled()
2575                            ? new InputEventConsistencyVerifier(
2576                                    this, 0, KeyEventDispatcher.class.getSimpleName()) : null;
2577
2578            public void notifyKeyEvent(KeyEvent event, int policyFlags) {
2579                final PendingEvent pendingEvent;
2580
2581                synchronized (mLock) {
2582                    pendingEvent = addPendingEventLocked(event, policyFlags);
2583                }
2584
2585                Message message = mInvocationHandler.obtainMessage(
2586                        InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent);
2587                mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS);
2588
2589                try {
2590                    // Accessibility services are exclusively not in the system
2591                    // process, therefore no need to clone the motion event to
2592                    // prevent tampering. It will be cloned in the IPC call.
2593                    mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence);
2594                } catch (RemoteException re) {
2595                    setOnKeyEventResult(false, pendingEvent.sequence);
2596                }
2597            }
2598
2599            public void setOnKeyEventResult(boolean handled, int sequence) {
2600                synchronized (mLock) {
2601                    PendingEvent pendingEvent = removePendingEventLocked(sequence);
2602                    if (pendingEvent != null) {
2603                        mInvocationHandler.removeMessages(
2604                                InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
2605                                pendingEvent);
2606                        pendingEvent.handled = handled;
2607                        finishPendingEventLocked(pendingEvent);
2608                    }
2609                }
2610            }
2611
2612            public void flush() {
2613                synchronized (mLock) {
2614                    cancelAllPendingEventsLocked();
2615                    if (mSentEventsVerifier != null) {
2616                        mSentEventsVerifier.reset();
2617                    }
2618                }
2619            }
2620
2621            private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) {
2622                final int sequence = event.getSequenceNumber();
2623                PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence);
2624                pendingEvent.next = mPendingEvents;
2625                mPendingEvents = pendingEvent;
2626                return pendingEvent;
2627            }
2628
2629            private PendingEvent removePendingEventLocked(int sequence) {
2630                PendingEvent previous = null;
2631                PendingEvent current = mPendingEvents;
2632
2633                while (current != null) {
2634                    if (current.sequence == sequence) {
2635                        if (previous != null) {
2636                            previous.next = current.next;
2637                        } else {
2638                            mPendingEvents = current.next;
2639                        }
2640                        current.next = null;
2641                        return current;
2642                    }
2643                    previous = current;
2644                    current = current.next;
2645                }
2646                return null;
2647            }
2648
2649            private void finishPendingEventLocked(PendingEvent pendingEvent) {
2650                if (!pendingEvent.handled) {
2651                    sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags);
2652                }
2653                // Nullify the event since we do not want it to be
2654                // recycled yet. It will be sent to the input filter.
2655                pendingEvent.event = null;
2656                recyclePendingEventLocked(pendingEvent);
2657            }
2658
2659            private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) {
2660                if (DEBUG) {
2661                    Slog.i(LOG_TAG, "Injecting event: " + event);
2662                }
2663                if (mSentEventsVerifier != null) {
2664                    mSentEventsVerifier.onKeyEvent(event, 0);
2665                }
2666                policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
2667                mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER,
2668                        policyFlags, 0, event).sendToTarget();
2669            }
2670
2671            private void cancelAllPendingEventsLocked() {
2672                while (mPendingEvents != null) {
2673                    PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence);
2674                    pendingEvent.handled = false;
2675                    mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
2676                            pendingEvent);
2677                    finishPendingEventLocked(pendingEvent);
2678                }
2679            }
2680        }
2681    }
2682
2683    private static final class PendingEvent {
2684        PendingEvent next;
2685
2686        KeyEvent event;
2687        int policyFlags;
2688        int sequence;
2689        boolean handled;
2690
2691        public void clear() {
2692            if (event != null) {
2693                event.recycle();
2694                event = null;
2695            }
2696            next = null;
2697            policyFlags = 0;
2698            sequence = 0;
2699            handled = false;
2700        }
2701    }
2702
2703    final class SecurityPolicy {
2704        private static final int VALID_ACTIONS =
2705            AccessibilityNodeInfo.ACTION_CLICK
2706            | AccessibilityNodeInfo.ACTION_LONG_CLICK
2707            | AccessibilityNodeInfo.ACTION_FOCUS
2708            | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS
2709            | AccessibilityNodeInfo.ACTION_SELECT
2710            | AccessibilityNodeInfo.ACTION_CLEAR_SELECTION
2711            | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS
2712            | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS
2713            | AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2714            | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2715            | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT
2716            | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT
2717            | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
2718            | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
2719            | AccessibilityNodeInfo.ACTION_COPY
2720            | AccessibilityNodeInfo.ACTION_PASTE
2721            | AccessibilityNodeInfo.ACTION_CUT
2722            | AccessibilityNodeInfo.ACTION_SET_SELECTION
2723            | AccessibilityNodeInfo.ACTION_EXPAND
2724            | AccessibilityNodeInfo.ACTION_COLLAPSE
2725            | AccessibilityNodeInfo.ACTION_DISMISS;
2726
2727        private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
2728            AccessibilityEvent.TYPE_VIEW_CLICKED
2729            | AccessibilityEvent.TYPE_VIEW_FOCUSED
2730            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2731            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2732            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2733            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2734            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2735            | AccessibilityEvent.TYPE_VIEW_SELECTED
2736            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
2737            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2738            | AccessibilityEvent.TYPE_VIEW_SCROLLED
2739            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2740            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
2741
2742        private int mActiveWindowId;
2743        private boolean mTouchInteractionInProgress;
2744
2745        private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
2746            final int eventType = event.getEventType();
2747            switch (eventType) {
2748                // All events that are for changes in a global window
2749                // state should *always* be dispatched.
2750                case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
2751                case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
2752                // All events generated by the user touching the
2753                // screen should *always* be dispatched.
2754                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
2755                case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
2756                case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
2757                case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
2758                case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
2759                case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
2760                // These will change the active window, so dispatch.
2761                case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
2762                case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
2763                    return true;
2764                }
2765                // All events for changes in window content should be
2766                // dispatched *only* if this window is the active one.
2767                default:
2768                    return event.getWindowId() == mActiveWindowId;
2769            }
2770        }
2771
2772        public void updateEventSourceLocked(AccessibilityEvent event) {
2773            if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
2774                event.setSource(null);
2775            }
2776        }
2777
2778        public void updateActiveWindow(int windowId, int eventType) {
2779            // The active window is either the window that has input focus or
2780            // the window that the user is currently touching. If the user is
2781            // touching a window that does not have input focus as soon as the
2782            // the user stops touching that window the focused window becomes
2783            // the active one.
2784            switch (eventType) {
2785                case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
2786                    if (getFocusedWindowId() == windowId) {
2787                        mActiveWindowId = windowId;
2788                    }
2789                } break;
2790                case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
2791                    // Do not allow delayed hover events to confuse us
2792                    // which the active window is.
2793                    if (mTouchInteractionInProgress) {
2794                        mActiveWindowId = windowId;
2795                    }
2796                } break;
2797            }
2798        }
2799
2800        public void onTouchInteractionStart() {
2801            mTouchInteractionInProgress = true;
2802        }
2803
2804        public void onTouchInteractionEnd() {
2805            mTouchInteractionInProgress = false;
2806            // We want to set the active window to be current immediately
2807            // after the user has stopped touching the screen since if the
2808            // user types with the IME he should get a feedback for the
2809            // letter typed in the text view which is in the input focused
2810            // window. Note that we always deliver hover accessibility events
2811            // (they are a result of user touching the screen) so change of
2812            // the active window before all hover accessibility events from
2813            // the touched window are delivered is fine.
2814            mActiveWindowId = getFocusedWindowId();
2815        }
2816
2817        public int getRetrievalAllowingWindowLocked() {
2818            return mActiveWindowId;
2819        }
2820
2821        public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
2822            return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId);
2823        }
2824
2825        public boolean canPerformActionLocked(Service service, int windowId, int action,
2826                Bundle arguments) {
2827            return canRetrieveWindowContent(service)
2828                && isRetrievalAllowingWindow(windowId)
2829                && isActionPermitted(action);
2830        }
2831
2832        public boolean canRetrieveWindowContent(Service service) {
2833            return (service.mAccessibilityServiceInfo.getCapabilities()
2834                    & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
2835        }
2836
2837        public void enforceCanRetrieveWindowContent(Service service) throws RemoteException {
2838            // This happens due to incorrect registration so make it apparent.
2839            if (!canRetrieveWindowContent(service)) {
2840                Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " +
2841                        "declare android:canRetrieveWindowContent.");
2842                throw new RemoteException();
2843            }
2844        }
2845
2846        public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
2847            final int callingUid = Binder.getCallingUid();
2848            if (callingUid == 0
2849                    || callingUid == Process.SYSTEM_UID
2850                    || callingUid == Process.SHELL_UID) {
2851                return mCurrentUserId;
2852            }
2853            final int callingUserId = UserHandle.getUserId(callingUid);
2854            if (callingUserId == userId) {
2855                return userId;
2856            }
2857            if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
2858                    && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
2859                throw new SecurityException("Call from user " + callingUserId + " as user "
2860                        + userId + " without permission INTERACT_ACROSS_USERS or "
2861                        + "INTERACT_ACROSS_USERS_FULL not allowed.");
2862            }
2863            if (userId == UserHandle.USER_CURRENT
2864                    || userId == UserHandle.USER_CURRENT_OR_SELF) {
2865                return mCurrentUserId;
2866            }
2867            throw new IllegalArgumentException("Calling user can be changed to only "
2868                    + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
2869        }
2870
2871        public boolean isCallerInteractingAcrossUsers(int userId) {
2872            final int callingUid = Binder.getCallingUid();
2873            return (Binder.getCallingPid() == android.os.Process.myPid()
2874                    || callingUid == Process.SHELL_UID
2875                    || userId == UserHandle.USER_CURRENT
2876                    || userId == UserHandle.USER_CURRENT_OR_SELF);
2877        }
2878
2879        private boolean isRetrievalAllowingWindow(int windowId) {
2880            return (mActiveWindowId == windowId);
2881        }
2882
2883        private boolean isActionPermitted(int action) {
2884             return (VALID_ACTIONS & action) != 0;
2885        }
2886
2887        private void enforceCallingPermission(String permission, String function) {
2888            if (OWN_PROCESS_ID == Binder.getCallingPid()) {
2889                return;
2890            }
2891            if (!hasPermission(permission)) {
2892                throw new SecurityException("You do not have " + permission
2893                        + " required to call " + function + " from pid="
2894                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2895            }
2896        }
2897
2898        private boolean hasPermission(String permission) {
2899            return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
2900        }
2901
2902        private int getFocusedWindowId() {
2903            try {
2904                // We call this only on window focus change or after touch
2905                // exploration gesture end and the shown windows are not that
2906                // many, so the linear look up is just fine.
2907                IBinder token = mWindowManagerService.getFocusedWindowToken();
2908                if (token != null) {
2909                    synchronized (mLock) {
2910                        int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens);
2911                        if (windowId < 0) {
2912                            windowId = getFocusedWindowIdLocked(token,
2913                                    getCurrentUserStateLocked().mWindowTokens);
2914                        }
2915                        return windowId;
2916                    }
2917                }
2918            } catch (RemoteException re) {
2919                /* ignore */
2920            }
2921            return -1;
2922        }
2923
2924        private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) {
2925            final int windowCount = windows.size();
2926            for (int i = 0; i < windowCount; i++) {
2927                if (windows.valueAt(i) == token) {
2928                    return windows.keyAt(i);
2929                }
2930            }
2931            return -1;
2932        }
2933    }
2934
2935    private class UserState {
2936        public final int mUserId;
2937
2938        // Non-transient state.
2939
2940        public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
2941            new RemoteCallbackList<IAccessibilityManagerClient>();
2942
2943        public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
2944                new SparseArray<AccessibilityConnectionWrapper>();
2945
2946        public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
2947
2948        // Transient state.
2949
2950        public final CopyOnWriteArrayList<Service> mBoundServices =
2951                new CopyOnWriteArrayList<Service>();
2952
2953        public final Map<ComponentName, Service> mComponentNameToServiceMap =
2954                new HashMap<ComponentName, Service>();
2955
2956        public final List<AccessibilityServiceInfo> mInstalledServices =
2957                new ArrayList<AccessibilityServiceInfo>();
2958
2959        public final Set<ComponentName> mBindingServices = new HashSet<ComponentName>();
2960
2961        public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
2962
2963        public final Set<ComponentName> mTouchExplorationGrantedServices =
2964                new HashSet<ComponentName>();
2965
2966        public int mHandledFeedbackTypes = 0;
2967
2968        public int mLastSentClientState = -1;
2969
2970        public boolean mIsAccessibilityEnabled;
2971        public boolean mIsTouchExplorationEnabled;
2972        public boolean mIsEnhancedWebAccessibilityEnabled;
2973        public boolean mIsDisplayMagnificationEnabled;
2974        public boolean mIsFilterKeyEventsEnabled;
2975        public boolean mHasDisplayColorAdjustment;
2976
2977        private Service mUiAutomationService;
2978        private IAccessibilityServiceClient mUiAutomationServiceClient;
2979
2980        private IBinder mUiAutomationServiceOwner;
2981        private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
2982                new DeathRecipient() {
2983            @Override
2984            public void binderDied() {
2985                mUiAutomationServiceOwner.unlinkToDeath(
2986                        mUiAutomationSerivceOnwerDeathRecipient, 0);
2987                mUiAutomationServiceOwner = null;
2988                if (mUiAutomationService != null) {
2989                    mUiAutomationService.binderDied();
2990                }
2991            }
2992        };
2993
2994        public UserState(int userId) {
2995            mUserId = userId;
2996        }
2997
2998        public int getClientState() {
2999            int clientState = 0;
3000            if (mIsAccessibilityEnabled) {
3001                clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
3002            }
3003            // Touch exploration relies on enabled accessibility.
3004            if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
3005                clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
3006            }
3007            return clientState;
3008        }
3009
3010        public void onSwitchToAnotherUser() {
3011            // Clear UI test automation state.
3012            if (mUiAutomationService != null) {
3013                mUiAutomationService.binderDied();
3014            }
3015
3016            // Unbind all services.
3017            unbindAllServicesLocked(this);
3018
3019            // Clear service management state.
3020            mBoundServices.clear();
3021            mBindingServices.clear();
3022
3023            // Clear event management state.
3024            mHandledFeedbackTypes = 0;
3025            mLastSentClientState = -1;
3026
3027            // Clear state persisted in settings.
3028            mEnabledServices.clear();
3029            mTouchExplorationGrantedServices.clear();
3030            mIsAccessibilityEnabled = false;
3031            mIsTouchExplorationEnabled = false;
3032            mIsEnhancedWebAccessibilityEnabled = false;
3033            mIsDisplayMagnificationEnabled = false;
3034        }
3035
3036        public void destroyUiAutomationService() {
3037            mUiAutomationService = null;
3038            mUiAutomationServiceClient = null;
3039            if (mUiAutomationServiceOwner != null) {
3040                mUiAutomationServiceOwner.unlinkToDeath(
3041                        mUiAutomationSerivceOnwerDeathRecipient, 0);
3042                mUiAutomationServiceOwner = null;
3043            }
3044        }
3045    }
3046
3047    private final class AccessibilityContentObserver extends ContentObserver {
3048
3049        private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
3050                Settings.Secure.ACCESSIBILITY_ENABLED);
3051
3052        private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
3053                Settings.Secure.TOUCH_EXPLORATION_ENABLED);
3054
3055        private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
3056                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
3057
3058        private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
3059                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
3060
3061        private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
3062                .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
3063
3064        private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
3065                .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
3066
3067        private final Uri mDisplayContrastEnabledUri = Settings.Secure.getUriFor(
3068                Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED);
3069        private final Uri mDisplayContrastUri = Settings.Secure.getUriFor(
3070                Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST);
3071        private final Uri mDisplayBrightnessUri = Settings.Secure.getUriFor(
3072                Settings.Secure.ACCESSIBILITY_DISPLAY_BRIGHTNESS);
3073
3074        private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(
3075                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
3076        private final Uri mDisplayInversionUri = Settings.Secure.getUriFor(
3077                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION);
3078
3079        private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
3080                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
3081        private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
3082                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
3083
3084        public AccessibilityContentObserver(Handler handler) {
3085            super(handler);
3086        }
3087
3088        public void register(ContentResolver contentResolver) {
3089            contentResolver.registerContentObserver(mAccessibilityEnabledUri,
3090                    false, this, UserHandle.USER_ALL);
3091            contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
3092                    false, this, UserHandle.USER_ALL);
3093            contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
3094                    false, this, UserHandle.USER_ALL);
3095            contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
3096                    false, this, UserHandle.USER_ALL);
3097            contentResolver.registerContentObserver(
3098                    mTouchExplorationGrantedAccessibilityServicesUri,
3099                    false, this, UserHandle.USER_ALL);
3100            contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
3101                    false, this, UserHandle.USER_ALL);
3102            contentResolver.registerContentObserver(
3103                    mDisplayContrastEnabledUri, false, this, UserHandle.USER_ALL);
3104            contentResolver.registerContentObserver(
3105                    mDisplayContrastUri, false, this, UserHandle.USER_ALL);
3106            contentResolver.registerContentObserver(
3107                    mDisplayBrightnessUri, false, this, UserHandle.USER_ALL);
3108            contentResolver.registerContentObserver(
3109                    mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL);
3110            contentResolver.registerContentObserver(
3111                    mDisplayInversionUri, false, this, UserHandle.USER_ALL);
3112            contentResolver.registerContentObserver(
3113                    mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
3114            contentResolver.registerContentObserver(
3115                    mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
3116        }
3117
3118        @Override
3119        public void onChange(boolean selfChange, Uri uri) {
3120            if (mAccessibilityEnabledUri.equals(uri)) {
3121                synchronized (mLock) {
3122                    // We will update when the automation service dies.
3123                    UserState userState = getCurrentUserStateLocked();
3124                    if (userState.mUiAutomationService == null) {
3125                        if (readAccessibilityEnabledSettingLocked(userState)) {
3126                            onUserStateChangedLocked(userState);
3127                        }
3128                    }
3129                }
3130            } else if (mTouchExplorationEnabledUri.equals(uri)) {
3131                synchronized (mLock) {
3132                    // We will update when the automation service dies.
3133                    UserState userState = getCurrentUserStateLocked();
3134                    if (userState.mUiAutomationService == null) {
3135                        if (readTouchExplorationEnabledSettingLocked(userState)) {
3136                            onUserStateChangedLocked(userState);
3137                        }
3138                    }
3139                }
3140            } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
3141                synchronized (mLock) {
3142                    // We will update when the automation service dies.
3143                    UserState userState = getCurrentUserStateLocked();
3144                    if (userState.mUiAutomationService == null) {
3145                        if (readDisplayMagnificationEnabledSettingLocked(userState)) {
3146                            onUserStateChangedLocked(userState);
3147                        }
3148                    }
3149                }
3150            } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
3151                synchronized (mLock) {
3152                    // We will update when the automation service dies.
3153                    UserState userState = getCurrentUserStateLocked();
3154                    if (userState.mUiAutomationService == null) {
3155                        if (readEnabledAccessibilityServicesLocked(userState)) {
3156                            onUserStateChangedLocked(userState);
3157                        }
3158                    }
3159                }
3160            } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
3161                synchronized (mLock) {
3162                    // We will update when the automation service dies.
3163                    UserState userState = getCurrentUserStateLocked();
3164                    if (userState.mUiAutomationService == null) {
3165                        if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
3166                            onUserStateChangedLocked(userState);
3167                        }
3168                    }
3169                }
3170            } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
3171                synchronized (mLock) {
3172                    // We will update when the automation service dies.
3173                    UserState userState = getCurrentUserStateLocked();
3174                    if (userState.mUiAutomationService == null) {
3175                        if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
3176                            onUserStateChangedLocked(userState);
3177                        }
3178                    }
3179                }
3180            } else if (mDisplayContrastEnabledUri.equals(uri)
3181                    || mDisplayInversionEnabledUri.equals(uri)
3182                    || mDisplayDaltonizerEnabledUri.equals(uri)
3183                    || mDisplayContrastUri.equals(uri)
3184                    || mDisplayBrightnessUri.equals(uri)
3185                    || mDisplayInversionUri.equals(uri)
3186                    || mDisplayDaltonizerUri.equals(uri)) {
3187                synchronized (mLock) {
3188                    // We will update when the automation service dies.
3189                    UserState userState = getCurrentUserStateLocked();
3190                    if (userState.mUiAutomationService == null) {
3191                        if (readDisplayColorAdjustmentSettingsLocked(userState)) {
3192                            updateDisplayColorAdjustmentSettingsLocked(userState);
3193                        }
3194                    }
3195                }
3196            }
3197        }
3198    }
3199}
3200