From 1c833479dd5a8b0e8aef736f1536080345c8e6b5 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Wed, 20 Oct 2021 19:00:22 +0800 Subject: [PATCH] Only register listeners if setView was success. Found a memory leak on ViewRootImpl. If the view wasn't been set to the VRI successfully, there would keep the registed listeners to the AccessibilityManager and DisplayManager forever because there didn't need to deatch anything from window. Another reasonable way is to register all listeners after setView success. Bug: 200843755 Test: manual, hard code to force addWindow fail and monitor no more ViewRootImpl object leaked to AccessibilityManager and DisplayManager. Change-Id: I3c9cc52d0ca4595c74c1dc3c51d286d9e6e3897f --- core/java/android/view/ViewRootImpl.java | 36 ++++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5a3a9d5bb5713..4c0c82fe5c2e9 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -820,11 +820,7 @@ public final class ViewRootImpl implements ViewParent, context); mCompatibleVisibilityInfo = new SystemUiVisibilityInfo(); mAccessibilityManager = AccessibilityManager.getInstance(context); - mAccessibilityManager.addAccessibilityStateChangeListener( - mAccessibilityInteractionConnectionManager, mHandler); mHighContrastTextManager = new HighContrastTextManager(); - mAccessibilityManager.addHighTextContrastStateChangeListener( - mHighContrastTextManager, mHandler); mViewConfiguration = ViewConfiguration.get(context); mDensity = context.getResources().getDisplayMetrics().densityDpi; mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi; @@ -1024,8 +1020,6 @@ public final class ViewRootImpl implements ViewParent, mView = view; mAttachInfo.mDisplayState = mDisplay.getState(); - mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); - mViewLayoutDirectionInitial = mView.getRawLayoutDirection(); mFallbackEventHandler.setView(view); mWindowAttributes.copyFrom(attrs); @@ -1218,6 +1212,7 @@ public final class ViewRootImpl implements ViewParent, "Unable to add window -- unknown error code " + res); } + registerListeners(); if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) { mUseBLASTAdapter = true; } @@ -1274,6 +1269,28 @@ public final class ViewRootImpl implements ViewParent, } } + /** + * Register any kind of listeners if setView was success. + */ + private void registerListeners() { + mAccessibilityManager.addAccessibilityStateChangeListener( + mAccessibilityInteractionConnectionManager, mHandler); + mAccessibilityManager.addHighTextContrastStateChangeListener( + mHighContrastTextManager, mHandler); + mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); + } + + /** + * Unregister all listeners while detachedFromWindow. + */ + private void unregisterListeners() { + mAccessibilityManager.removeAccessibilityStateChangeListener( + mAccessibilityInteractionConnectionManager); + mAccessibilityManager.removeHighTextContrastStateChangeListener( + mHighContrastTextManager); + mDisplayManager.unregisterDisplayListener(mDisplayListener); + } + private void setTag() { final String[] split = mWindowAttributes.getTitle().toString().split("\\."); if (split.length > 0) { @@ -5016,10 +5033,6 @@ public final class ViewRootImpl implements ViewParent, } mAccessibilityInteractionConnectionManager.ensureNoConnection(); - mAccessibilityManager.removeAccessibilityStateChangeListener( - mAccessibilityInteractionConnectionManager); - mAccessibilityManager.removeHighTextContrastStateChangeListener( - mHighContrastTextManager); removeSendWindowContentChangedCallback(); destroyHardwareRenderer(); @@ -5052,8 +5065,7 @@ public final class ViewRootImpl implements ViewParent, mInputEventReceiver = null; } - mDisplayManager.unregisterDisplayListener(mDisplayListener); - + unregisterListeners(); unscheduleTraversals(); }