Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8cfb373 authored by Phil Weaver's avatar Phil Weaver
Browse files

Improve handling of crashing a11y services.

We were confusing handling of services that were unbound with
those that had crashed. We would lose track of services that
has crashed, start new ones, and then when the system restarted
a killed services we would have multiple instances running. It
was possible for this to get very out of hand.

Bug: 30306689
Change-Id: I4e63d25b6d2fec3ec68f450a4602898c43a2b2ad
parent 0cf4d47a
Loading
Loading
Loading
Loading
+22 −13
Original line number Diff line number Diff line
@@ -1111,9 +1111,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {

    private void addServiceLocked(Service service, UserState userState) {
        try {
            if (!userState.mBoundServices.contains(service)) {
                service.onAdded();
                userState.mBoundServices.add(service);
                userState.mComponentNameToServiceMap.put(service.mComponentName, service);
            }
        } catch (RemoteException re) {
            /* do nothing */
        }
@@ -1126,8 +1128,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     */
    private void removeServiceLocked(Service service, UserState userState) {
        userState.mBoundServices.remove(service);
        userState.mComponentNameToServiceMap.remove(service.mComponentName);
        service.onRemoved();
        // It may be possible to bind a service twice, which confuses the map. Rebuild the map
        // to make sure we can still reach a service
        userState.mComponentNameToServiceMap.clear();
        for (int i = 0; i < userState.mBoundServices.size(); i++) {
            Service boundService = userState.mBoundServices.get(i);
            userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService);
        }
    }

    /**
@@ -2324,15 +2332,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        }

        /**
         * Unbinds form the accessibility service and removes it from the data
         * Unbinds from the accessibility service and removes it from the data
         * structures for service management.
         *
         * @return True if unbinding is successful.
         */
        public boolean unbindLocked() {
            if (mService == null) {
                return false;
            }
            UserState userState = getUserStateLocked(mUserId);
            getKeyEventDispatcher().flush(this);
            if (!mIsAutomation) {
@@ -3033,7 +3038,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            /* do nothing - #binderDied takes care */
            binderDied();
        }

        public void onAdded() throws RemoteException {
@@ -3062,14 +3067,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
        }

        public void unlinkToOwnDeathLocked() {
            if (mService != null) {
                mService.unlinkToDeath(this, 0);
            }
        }

        public void resetLocked() {
            try {
                // Clear the proxy in the other process so this
                // IAccessibilityServiceConnection can be garbage collected.
                if (mServiceInterface != null) {
                    mServiceInterface.init(null, mId, null);
                }
            } catch (RemoteException re) {
                /* ignore */
            }
@@ -3093,10 +3102,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                mWasConnectedAndDied = true;
                getKeyEventDispatcher().flush(this);
                UserState userState = getUserStateLocked(mUserId);
                // The death recipient is unregistered in removeServiceLocked
                removeServiceLocked(this, userState);
                resetLocked();
                if (mIsAutomation) {
                    // This is typically done when unbinding, but UiAutomation isn't bound.
                    removeServiceLocked(this, userState);
                    // We no longer have an automation service, so restore
                    // the state based on values in the settings database.
                    userState.mInstalledServices.remove(mAccessibilityServiceInfo);