diff options
| author | 2022-11-18 18:55:52 +0000 | |
|---|---|---|
| committer | 2022-11-18 18:55:52 +0000 | |
| commit | 3fe124cd7f262b9de73e781e4e23a39725e97d86 (patch) | |
| tree | 2ddedef23ed0af539279984eae10f1a98cbc3307 | |
| parent | bd28d80cfedd8710b5c2caec9245bb40f05a2a32 (diff) | |
| parent | 4873e34e898d9de1cad86581fef74fbbfb5bc21f (diff) | |
Merge "Fix activity leak bug"
| -rw-r--r-- | core/java/android/animation/AnimationHandler.java | 59 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 13 |
2 files changed, 50 insertions, 22 deletions
diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java index dcabf57cb8a9..df8a50a1fa5c 100644 --- a/core/java/android/animation/AnimationHandler.java +++ b/core/java/android/animation/AnimationHandler.java @@ -19,10 +19,10 @@ package android.animation; import android.os.SystemClock; import android.os.SystemProperties; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; import android.view.Choreographer; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -78,7 +78,7 @@ public class AnimationHandler { * store visible (foreground) requestors; if the set size reaches zero, there are no * objects in the foreground and it is time to pause animators. */ - private final ArraySet<Object> mAnimatorRequestors = new ArraySet<>(); + private final ArrayList<WeakReference<Object>> mAnimatorRequestors = new ArrayList<>(); private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { @Override @@ -141,19 +141,9 @@ public class AnimationHandler { * tracking obsolete+enabled requestors. */ public static void removeRequestor(Object requestor) { - getInstance().removeRequestorImpl(requestor); - } - - private void removeRequestorImpl(Object requestor) { - // Also request disablement, in case that requestor was the sole object keeping - // animators un-paused - requestAnimatorsEnabled(false, requestor); - mAnimatorRequestors.remove(requestor); + getInstance().requestAnimatorsEnabledImpl(false, requestor); if (LOCAL_LOGV) { - Log.v(TAG, "removeRequestorImpl for " + requestor); - for (int i = 0; i < mAnimatorRequestors.size(); ++i) { - Log.v(TAG, "animatorRequesters " + i + " = " + mAnimatorRequestors.valueAt(i)); - } + Log.v(TAG, "removeRequestor for " + requestor); } } @@ -173,10 +163,36 @@ public class AnimationHandler { private void requestAnimatorsEnabledImpl(boolean enable, Object requestor) { boolean wasEmpty = mAnimatorRequestors.isEmpty(); setAnimatorPausingEnabled(isPauseBgAnimationsEnabledInSystemProperties()); - if (enable) { - mAnimatorRequestors.add(requestor); - } else { - mAnimatorRequestors.remove(requestor); + synchronized (mAnimatorRequestors) { + // Only store WeakRef objects to avoid leaks + if (enable) { + // First, check whether such a reference is already on the list + WeakReference<Object> weakRef = null; + for (int i = mAnimatorRequestors.size() - 1; i >= 0; --i) { + WeakReference<Object> ref = mAnimatorRequestors.get(i); + Object referent = ref.get(); + if (referent == requestor) { + weakRef = ref; + } else if (referent == null) { + // Remove any reference that has been cleared + mAnimatorRequestors.remove(i); + } + } + if (weakRef == null) { + weakRef = new WeakReference<>(requestor); + mAnimatorRequestors.add(weakRef); + } + } else { + for (int i = mAnimatorRequestors.size() - 1; i >= 0; --i) { + WeakReference<Object> ref = mAnimatorRequestors.get(i); + Object referent = ref.get(); + if (referent == requestor || referent == null) { + // remove requested item or item that has been cleared + mAnimatorRequestors.remove(i); + } + } + // If a reference to the requestor wasn't in the list, nothing to remove + } } if (!sAnimatorPausingEnabled) { // Resume any animators that have been paused in the meantime, otherwise noop @@ -198,9 +214,12 @@ public class AnimationHandler { } } if (LOCAL_LOGV) { - Log.v(TAG, enable ? "enable" : "disable" + " animators for " + requestor); + Log.v(TAG, (enable ? "enable" : "disable") + " animators for " + requestor + + " with pauseDelay of " + Animator.getBackgroundPauseDelay()); for (int i = 0; i < mAnimatorRequestors.size(); ++i) { - Log.v(TAG, "animatorRequesters " + i + " = " + mAnimatorRequestors.valueAt(i)); + Log.v(TAG, "animatorRequestors " + i + " = " + + mAnimatorRequestors.get(i) + " with referent " + + mAnimatorRequestors.get(i).get()); } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a441f3f05fda..0f970bf4f91c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1409,7 +1409,11 @@ public final class ViewRootImpl implements ViewParent, mFirstPostImeInputStage = earlyPostImeStage; mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix; - AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); + if (!mRemoved || !mAppVisible) { + AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); + } else if (LOCAL_LOGV) { + Log.v(mTag, "setView() enabling visibility when removed"); + } } } } @@ -1760,7 +1764,12 @@ public final class ViewRootImpl implements ViewParent, mAppVisibilityChanged = true; scheduleTraversals(); } - AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); + // Only enable if the window is not already removed (via earlier call to doDie()) + if (!mRemoved || !mAppVisible) { + AnimationHandler.requestAnimatorsEnabled(mAppVisible, this); + } else if (LOCAL_LOGV) { + Log.v(mTag, "handleAppVisibility() enabling visibility when removed"); + } } } |