Fix Toast leak in AccessibilityManager
AccessibilityManager registers a client object in the constructor.
So only create a AccessibilityManager when trying to send an accessibility event,
as there may be multiple ToastPresenters initialized without being used: from the client app and SystemUi.
Test: atest WindowUntrustedTouchTest
atest ToastWindowTest
atest ToastPresenterTest
atest ToastUITest
Bug: 298593662
Change-Id: Ie8a4440338d25d521eb036dc4531c820d5a35267
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 89271b5..6884e63 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -89,9 +89,10 @@
return view;
}
+ private final WeakReference<Context> mContext;
private final Resources mResources;
private final WeakReference<WindowManager> mWindowManager;
- private final WeakReference<AccessibilityManager> mAccessibilityManager;
+ private final IAccessibilityManager mAccessibilityManagerService;
private final INotificationManager mNotificationManager;
private final String mPackageName;
private final String mContextPackageName;
@@ -101,21 +102,14 @@
public ToastPresenter(Context context, IAccessibilityManager accessibilityManager,
INotificationManager notificationManager, String packageName) {
+ mContext = new WeakReference<>(context);
mResources = context.getResources();
mWindowManager = new WeakReference<>(context.getSystemService(WindowManager.class));
mNotificationManager = notificationManager;
mPackageName = packageName;
mContextPackageName = context.getPackageName();
mParams = createLayoutParams();
-
- // 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 WeakReference<>(
- new AccessibilityManager(context, accessibilityManager, context.getUserId()));
+ mAccessibilityManagerService = accessibilityManager;
}
public String getPackageName() {
@@ -306,11 +300,20 @@
* enabled.
*/
public void trySendAccessibilityEvent(View view, String packageName) {
- final AccessibilityManager accessibilityManager = mAccessibilityManager.get();
- if (accessibilityManager == null) {
+ final Context context = mContext.get();
+ if (context == null) {
return;
}
+ // 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(context,
+ mAccessibilityManagerService, context.getUserId());
+
if (!accessibilityManager.isEnabled()) {
accessibilityManager.removeClient();
return;