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

Commit cda1b9cc authored by Sally's avatar Sally
Browse files

Unregister IA11yManagerClient in ToastPresenter

AccessibilityManager is used to send an a11y event when the Toast is
shown, so unregister the client after it's shown

Test: Track clients in A11yManagerService before and after
multiple toasts are shown with adb shell dumpsys accessibility,
atest ToastUITest
Bug: 189010828

Change-Id: Ie4759d2f67ab9e3149d44169b812d8ec2316c266
parent 4a41eca7
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ public class ToastPresenter {
    private final Context mContext;
    private final Resources mResources;
    private final WindowManager mWindowManager;
    private final AccessibilityManager mAccessibilityManager;
    private final IAccessibilityManager mAccessibilityManager;
    private final INotificationManager mNotificationManager;
    private final String mPackageName;
    private final WindowManager.LayoutParams mParams;
@@ -83,16 +83,7 @@ public class ToastPresenter {
        mWindowManager = context.getSystemService(WindowManager.class);
        mNotificationManager = notificationManager;
        mPackageName = packageName;

        // We obtain AccessibilityManager manually via its constructor instead of using method
        // AccessibilityManager.getInstance() for 2 reasons:
        //   1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
        //   2. getInstance() caches the instance for the process even if we pass a different
        //      context to it. This is problematic for multi-user because callers can pass a context
        //      created via Context.createContextAsUser().
        mAccessibilityManager = new AccessibilityManager(context, accessibilityManager,
                context.getUserId());

        mAccessibilityManager = accessibilityManager;
        mParams = createLayoutParams();
    }

@@ -283,7 +274,16 @@ public class ToastPresenter {
     * enabled.
     */
    public void trySendAccessibilityEvent(View view, String packageName) {
        if (!mAccessibilityManager.isEnabled()) {
        // We obtain AccessibilityManager manually via its constructor instead of using method
        // AccessibilityManager.getInstance() for 2 reasons:
        //   1. We want to be able to inject IAccessibilityManager in tests to verify behavior.
        //   2. getInstance() caches the instance for the process even if we pass a different
        //      context to it. This is problematic for multi-user because callers can pass a context
        //      created via Context.createContextAsUser().
        final AccessibilityManager accessibilityManager =
                new AccessibilityManager(mContext, mAccessibilityManager, mContext.getUserId());
        if (!accessibilityManager.isEnabled()) {
            accessibilityManager.removeClient();
            return;
        }
        AccessibilityEvent event = AccessibilityEvent.obtain(
@@ -291,7 +291,11 @@ public class ToastPresenter {
        event.setClassName(Toast.class.getName());
        event.setPackageName(packageName);
        view.dispatchPopulateAccessibilityEvent(event);
        mAccessibilityManager.sendAccessibilityEvent(event);
        accessibilityManager.sendAccessibilityEvent(event);
        // Every new instance of A11yManager registers an IA11yManagerClient object with the
        // backing service. This client isn't removed until the calling process is destroyed,
        // causing a leak here. We explicitly remove the client.
        accessibilityManager.removeClient();
    }

    private void addToastView() {
+9 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ public class ToastUITest extends SysuiTestCase {
    private static final String PACKAGE_NAME_1 = "com.example1.test";
    private static final Binder TOKEN_1 = new Binder();
    private static final Binder WINDOW_TOKEN_1 = new Binder();
    private static final int USER_ID = 1;

    private static final int UID_2 = 10256;
    private static final String PACKAGE_NAME_2 = "com.example2.test";
@@ -226,6 +227,14 @@ public class ToastUITest extends SysuiTestCase {
        assertThat(event.getPackageName()).isEqualTo(PACKAGE_NAME_1);
    }

    @Test
    public void testShowToast_accessibilityManagerClientIsRemoved() throws Exception {
        when(mContextSpy.getUserId()).thenReturn(USER_ID);
        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,
                null);
        verify(mAccessibilityManager).removeClient(any(), eq(USER_ID));
    }

    @Test
    public void testHideToast_removesView() throws Exception {
        mToastUI.showToast(UID_1, PACKAGE_NAME_1, TOKEN_1, TEXT, WINDOW_TOKEN_1, Toast.LENGTH_LONG,