Merge "Unregister IA11yManagerClient in ToastPresenter" into sc-dev

This commit is contained in:
Sally Yuen
2021-06-11 19:14:45 +00:00
committed by Android (Google) Code Review
2 changed files with 26 additions and 13 deletions

View File

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

View File

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