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
This commit is contained in:
Sally
2021-06-02 21:25:52 +00:00
parent 7a2b7fc43f
commit 4a41eca71b
5 changed files with 74 additions and 0 deletions

View File

@@ -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
*/

View File

@@ -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)

View File

@@ -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

View File

@@ -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));
}
}
}

View File

@@ -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("}]");
}