Merge "Fix another animation leak" into pi-dev
am: 8d23a78b40
Change-Id: Icedc9e648d8736b388b64cabfa78768da5a1142e
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user