OSDN Git Service

[Magnifier-44] Fix memory leak caused by callback
authorMihai Popa <popam@google.com>
Wed, 6 Jun 2018 13:30:54 +0000 (14:30 +0100)
committerMihai Popa <popam@google.com>
Fri, 8 Jun 2018 10:15:04 +0000 (10:15 +0000)
Before this CL, the magnifier could have caused a memory leak when:
- in Editor we give the magnifier a callback that updates the visibility
of the handles after the magnifier is drawn. This holds a reference to
the HandleView, which in turn has a reference to the containing Activity
- the callback is set on the InternalPopupWindow, in order to be run
after the next #doDraw call
- #doDraw is post'd as a runnable to the UI thread
- the magnifier is dismissed and the activity is destroyed
- when the garbage collection happens, the InternalPopupWindow cannot be
collected, because either:
  -- there is still a reference to the job expected to run #doDraw
  -- there is still a pixel copy that has to finish. We keep a reference
     to the InternalPopupWindow in use when the pixel copy was requested
     in order to compare it with the current one, and dismiss the pixel
     copy result if the instance has changed
- both options above mean that we will still have a reference to the
callback that sets the visibility of the handles, so a reference to the
containing Activity. The Activity is, therefore, leaked.

This CL cleares the handle visibility callback when the magnifier is
dismissed, such that the unnecessary reference to the Activity will not
be held.

Bug: 80279783
Test: verified with leakcanary that the memory leak no longer exists
Change-Id: I65c77eb12d2778c76fe631b55e6a7164fbf487f1

core/java/android/widget/Editor.java

index d07721a..058736a 100644 (file)
@@ -4930,6 +4930,7 @@ public class Editor {
 
         protected final void dismissMagnifier() {
             if (mMagnifierAnimator != null) {
+                mMagnifierAnimator.mMagnifier.setOnOperationCompleteCallback(null);
                 mMagnifierAnimator.dismiss();
                 mRenderCursorRegardlessTiming = false;
                 resumeBlink();