Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 49958: Close a view leak due to lossy onAnimationEnd callback #49959

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

knappam
Copy link
Contributor

@knappam knappam commented Mar 11, 2025

Summary:

Android's onAnimationEnd callback is lossy and ocasionally just does not fire. However the LayoutAnimationController maintains a sparse array of animations (with Strong View refs) that is only cleaned when the onAnimationEnd callback is invoked. This results in a leak of Android View objects over time.

To avoid this, the Strong View refs are migrated to WeakReference's and the associated sparse array is cleaned of any invalid layout animations in response to the reset() call.

This closes two leaks:

  1. Unbound growth in LayoutAnimationController::mLayoutHandlers
  2. Pinning View objects into memory as the sole remaining GC root

Changelog:

  1. Made OpacityAnimation and PositionAndSizeAnimation classes hold weak refs to views only
  2. Added a method to LayoutHandlingAnimation to surface if their view ref is gone
  3. Added cleanup for Animation with bad view refs

Pick one each for the category and type tags:

[ANDROID] [Fixed]- Fixes memory leak

Test Plan

  • Primarily code inspection and regression given the intermittent nature of Android's failure to execute the callback.

Android's onAnimationEnd callback is lossy and ocasionally just does not
fire.  However the LayoutAnimationController maintains a sparse array of
animations (with Strong View refs) that is only cleaned when the
onAnimationEnd callback is invoked.  This results in a leak of Android
View objects over time.

To avoid this, the Strong View refs are migrated to WeakReference's and
the associated sparse array is cleaned of any invalid layout animations
in response to the reset() call.

This closes two leaks:
1. Unbound growth in LayoutAnimationController::mLayoutHandlers
2. Pinning View objects into memory as the sole remaining GC root
@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. amazon Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Mar 11, 2025
Copy link
Member

@javache javache left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this!

Comment on lines +90 to +95
for (int i = mLayoutHandlers.size() - 1; i >= 0; i--) {
LayoutHandlingAnimation animation = mLayoutHandlers.valueAt(i);
if (!animation.isValid()) {
mLayoutHandlers.removeAt(i);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shouldn't we fully clear out mLayoutHandlers here?

Copy link
Contributor Author

@knappam knappam Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my initial thought as well, but the persistence of Animations across UI operations batch runs (one source of call chain to reset()) almost looks intentional. Because of that, I was worried about unintentionally breaking a non-obvious, yet intentional path in the original implementation.

This down-scoped cleanup will allow Animation objects to persist longer than their useful time but should be safe. A more complete cleanup would remove the Animation objects sooner but at some risk of regression.

@facebook-github-bot
Copy link
Contributor

@javache has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@cortinico cortinico added Partner p: Amazon Partner: Amazon and removed amazon labels Mar 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Amazon Partner: Amazon Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants