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

Commit 4a41eca7 authored by Sally's avatar Sally
Browse files

Add AccessibilityManager#removeClient

Whenever an app makes a Text toast, this gets routed through systemUI
starting from R. Two A11yManagerClients are registered with
A11yManagerService for every toast. Since clients aren't removed until
the process is killed, there are a bunch of clients from systemui
hanging around and potentially cause the system to crash.

We add a way here to explicitly unregister a client

Test: build and flash,
atest android.view.accessibility.AccessibilityManagerTest
Bug: 189010828

Change-Id: I3f71bac475b4539c7be5b328adeb0be35a0b5543
parent 7a2b7fc4
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -516,6 +516,25 @@ public final class AccessibilityManager {
        return mClient;
    }

    /**
     * Unregisters the IAccessibilityManagerClient from the backing service
     * @hide
     */
    public boolean removeClient() {
        synchronized (mLock) {
            IAccessibilityManager service = getServiceLocked();
            if (service == null) {
                return false;
            }
            try {
                return service.removeClient(mClient, mUserId);
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
            }
        }
        return false;
    }

    /**
     * @hide
     */
+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ interface IAccessibilityManager {

    long addClient(IAccessibilityManagerClient client, int userId);

    boolean removeClient(IAccessibilityManagerClient client, int userId);

    List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);

    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+7 −0
Original line number Diff line number Diff line
@@ -115,6 +115,13 @@ public class AccessibilityManagerTest {
        return manager;
    }

    @Test
    public void testRemoveManager() throws Exception {
        AccessibilityManager manager = createManager(WITH_A11Y_ENABLED);
        manager.removeClient();
        verify(mMockService).removeClient(manager.getClient(), UserHandle.USER_CURRENT);
    }

    @Test
    public void testGetAccessibilityServiceList() throws Exception {
        // create a list of installed accessibility services the mock service returns
+36 −0
Original line number Diff line number Diff line
@@ -709,6 +709,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        }
    }

    @Override
    public boolean removeClient(IAccessibilityManagerClient callback, int userId) {
        // TODO(b/190216606): Add tracing for removeClient when implementation is the same in master

        synchronized (mLock) {
            final int resolvedUserId = mSecurityPolicy
                    .resolveCallingUserIdEnforcingPermissionsLocked(userId);

            AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
            if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
                boolean unregistered = mGlobalClients.unregister(callback);
                if (DEBUG) {
                    Slog.i(LOG_TAG,
                            "Removed global client for pid:" + Binder.getCallingPid() + "state: "
                                    + unregistered);
                }
                return unregistered;
            } else {
                boolean unregistered = userState.mUserClients.unregister(callback);
                if (DEBUG) {
                    Slog.i(LOG_TAG, "Removed user client for pid:" + Binder.getCallingPid()
                            + " and userId:" + resolvedUserId + "state: " + unregistered);
                }
                return unregistered;
            }
        }
    }

    @Override
    public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
        if (mTraceManager.isA11yTracingEnabled()) {
@@ -3271,6 +3299,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                pw.println();
            }
            mA11yWindowManager.dump(fd, pw, args);
            pw.println("Global client list info:{");
            mGlobalClients.dump(pw, "    Client list ");
            pw.println("    Registered clients:{");
            for (int i = 0; i < mGlobalClients.getRegisteredCallbackCount(); i++) {
                AccessibilityManagerService.Client client = (AccessibilityManagerService.Client)
                        mGlobalClients.getRegisteredCallbackCookie(i);
                pw.append(Arrays.toString(client.mPackageNames));
            }
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.internal.accessibility.AccessibilityShortcutController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -573,6 +574,15 @@ class AccessibilityUserState {
                pw.append(componentName.toShortString());
            }
        }
        pw.println("}");
        pw.println("     Client list info:{");
        mUserClients.dump(pw, "          Client list ");
        pw.println("          Registered clients:{");
        for (int i = 0; i < mUserClients.getRegisteredCallbackCount(); i++) {
            AccessibilityManagerService.Client client = (AccessibilityManagerService.Client)
                    mUserClients.getRegisteredCallbackCookie(i);
            pw.append(Arrays.toString(client.mPackageNames));
        }
        pw.println("}]");
    }