From c5e7b955af75beecf57fb25b249534cb42e39db1 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Wed, 5 Feb 2025 15:38:27 -0800 Subject: [PATCH] [Memory Leak] Fix leak of TouchInteractionService from DisplayInfoChangeListener Fix: 394672098 Flag: NONE - released code Test: manual Change-Id: I99bfd783e8be34066e29072f5c1a6719802bde05 --- .../RecentsAnimationDeviceState.java | 31 +++++++++++++------ .../quickstep/TouchInteractionService.java | 7 +++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index e1e962add6..090ccdc869 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -114,7 +114,6 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E private final RotationTouchHelper mRotationTouchHelper; private final TaskStackChangeListener mPipListener; - private final DaggerSingletonTracker mLifeCycle; // Cache for better performance since it doesn't change at runtime. private final boolean mCanImeRenderGesturalNavButtons = InputMethodService.canImeRenderGesturalNavButtons(); @@ -152,16 +151,15 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E mExclusionManager = exclusionManager; mContextualSearchStateManager = contextualSearchStateManager; mRotationTouchHelper = rotationTouchHelper; - mLifeCycle = lifeCycle; mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false); // Register for exclusion updates - mLifeCycle.addCloseable(this::unregisterExclusionListener); + lifeCycle.addCloseable(this::unregisterExclusionListener); // Register for display changes changes mDisplayController.addChangeListener(this); onDisplayInfoChanged(context, mDisplayController.getInfo(), CHANGE_ALL); - mLifeCycle.addCloseable(() -> mDisplayController.removeChangeListener(this)); + lifeCycle.addCloseable(() -> mDisplayController.removeChangeListener(this)); if (mIsOneHandedModeSupported) { Uri oneHandedUri = Settings.Secure.getUriFor(ONE_HANDED_ENABLED); @@ -169,7 +167,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E enabled -> mIsOneHandedModeEnabled = enabled; settingsCache.register(oneHandedUri, onChangeListener); mIsOneHandedModeEnabled = settingsCache.getValue(oneHandedUri); - mLifeCycle.addCloseable(() -> settingsCache.unregister(oneHandedUri, onChangeListener)); + lifeCycle.addCloseable(() -> settingsCache.unregister(oneHandedUri, onChangeListener)); } else { mIsOneHandedModeEnabled = false; } @@ -180,7 +178,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E enabled -> mIsSwipeToNotificationEnabled = enabled; settingsCache.register(swipeBottomNotificationUri, onChangeListener); mIsSwipeToNotificationEnabled = settingsCache.getValue(swipeBottomNotificationUri); - mLifeCycle.addCloseable( + lifeCycle.addCloseable( () -> settingsCache.unregister(swipeBottomNotificationUri, onChangeListener)); Uri setupCompleteUri = Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE); @@ -188,7 +186,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E if (!mIsUserSetupComplete) { SettingsCache.OnChangeListener userSetupChangeListener = e -> mIsUserSetupComplete = e; settingsCache.register(setupCompleteUri, userSetupChangeListener); - mLifeCycle.addCloseable( + lifeCycle.addCloseable( () -> settingsCache.unregister(setupCompleteUri, userSetupChangeListener)); } @@ -210,15 +208,19 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E } }; TaskStackChangeListeners.getInstance().registerTaskStackListener(mPipListener); - mLifeCycle.addCloseable(() -> + lifeCycle.addCloseable(() -> TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mPipListener)); } /** * Adds a listener for the nav mode change, guaranteed to be called after the device state's * mode has changed. + * + * @return Added {@link DisplayInfoChangeListener} so that caller is + * responsible for removing the listener from {@link DisplayController} to avoid memory leak. */ - public void addNavigationModeChangedCallback(Runnable callback) { + public DisplayController.DisplayInfoChangeListener addNavigationModeChangedCallback( + Runnable callback) { DisplayController.DisplayInfoChangeListener listener = (context, info, flags) -> { if ((flags & CHANGE_NAVIGATION_MODE) != 0) { callback.run(); @@ -226,7 +228,16 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E }; mDisplayController.addChangeListener(listener); callback.run(); - mLifeCycle.addCloseable(() -> mDisplayController.removeChangeListener(listener)); + return listener; + } + + /** + * Remove the {DisplayController.DisplayInfoChangeListener} added from + * {@link #addNavigationModeChangedCallback} when {@link TouchInteractionService} is destroyed. + */ + public void removeDisplayInfoChangeListener( + DisplayController.DisplayInfoChangeListener listener) { + mDisplayController.removeChangeListener(listener); } @Override diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 51e59ffdb8..d77516e4af 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -576,6 +576,8 @@ public class TouchInteractionService extends Service { private DesktopAppLaunchTransitionManager mDesktopAppLaunchTransitionManager; + private DisplayController.DisplayInfoChangeListener mDisplayInfoChangeListener; + @Override public void onCreate() { super.onCreate(); @@ -605,7 +607,8 @@ public class TouchInteractionService extends Service { // Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized. LockedUserState.get(this).runOnUserUnlocked(mUserUnlockedRunnable); - mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged); + mDisplayInfoChangeListener = + mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged); ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener); } @@ -757,7 +760,7 @@ public class TouchInteractionService extends Service { mDesktopAppLaunchTransitionManager.unregisterTransitions(); } mDesktopAppLaunchTransitionManager = null; - + mDeviceState.removeDisplayInfoChangeListener(mDisplayInfoChangeListener); LockedUserState.get(this).removeOnUserUnlockedRunnable(mUserUnlockedRunnable); ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener); super.onDestroy();