Merge "Fix another animation leak" into pi-dev

am: 8d23a78b40

Change-Id: Icedc9e648d8736b388b64cabfa78768da5a1142e
This commit is contained in:
Jorim Jaggi
2018-04-06 14:11:27 -07:00
committed by android-build-merger
2 changed files with 48 additions and 8 deletions

View File

@@ -37,6 +37,8 @@ class AnimatingAppWindowTokenRegistry {
private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>(); private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>();
private boolean mEndingDeferredFinish;
/** /**
* Notifies that an {@link AppWindowToken} has started animating. * Notifies that an {@link AppWindowToken} has started animating.
*/ */
@@ -50,6 +52,11 @@ class AnimatingAppWindowTokenRegistry {
void notifyFinished(AppWindowToken token) { void notifyFinished(AppWindowToken token) {
mAnimatingTokens.remove(token); mAnimatingTokens.remove(token);
mFinishedTokens.remove(token); mFinishedTokens.remove(token);
// If we were the last token, make sure the end all deferred finishes.
if (mAnimatingTokens.isEmpty()) {
endDeferringFinished();
}
} }
/** /**
@@ -78,16 +85,28 @@ class AnimatingAppWindowTokenRegistry {
} }
private void endDeferringFinished() { private void endDeferringFinished() {
// Copy it into a separate temp list to avoid modifying the collection while iterating as
// calling the callback may call back into notifyFinished. // Don't start recursing. Running the finished listener invokes notifyFinished, which may
for (int i = mFinishedTokens.size() - 1; i >= 0; i--) { // invoked us again.
mTmpRunnableList.add(mFinishedTokens.valueAt(i)); if (mEndingDeferredFinish) {
return;
} }
mFinishedTokens.clear(); try {
for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) { mEndingDeferredFinish = true;
mTmpRunnableList.get(i).run();
// Copy it into a separate temp list to avoid modifying the collection while iterating
// as calling the callback may call back into notifyFinished.
for (int i = mFinishedTokens.size() - 1; i >= 0; i--) {
mTmpRunnableList.add(mFinishedTokens.valueAt(i));
}
mFinishedTokens.clear();
for (int i = mTmpRunnableList.size() - 1; i >= 0; i--) {
mTmpRunnableList.get(i).run();
}
mTmpRunnableList.clear();
} finally {
mEndingDeferredFinish = false;
} }
mTmpRunnableList.clear();
} }
void dump(PrintWriter pw, String header, String prefix) { void dump(PrintWriter pw, String header, String prefix) {

View File

@@ -88,4 +88,25 @@ public class AnimatingAppWindowTokenRegistryTest extends WindowTestsBase {
verify(mMockEndDeferFinishCallback1).run(); verify(mMockEndDeferFinishCallback1).run();
verifyZeroInteractions(mMockEndDeferFinishCallback2); verifyZeroInteractions(mMockEndDeferFinishCallback2);
} }
@Test
public void testContainerRemoved() throws Exception {
final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
"window2").mAppToken;
final AnimatingAppWindowTokenRegistry registry =
window1.getStack().getAnimatingAppWindowTokenRegistry();
window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
assertTrue(window1.isSelfAnimating());
assertTrue(window2.isSelfAnimating());
// Make sure that first animation finish is deferred, and removing the second window stops
// finishes all pending deferred finishings.
registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1);
window2.setParent(null);
verify(mMockEndDeferFinishCallback1).run();
}
} }