Merge "Fix issue with 0 duration animations"

This commit is contained in:
Jorim Jaggi
2018-01-04 11:47:34 +00:00
committed by Android (Google) Code Review
5 changed files with 65 additions and 16 deletions

View File

@@ -1923,6 +1923,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mService.unregisterPointerEventListener(mService.mMousePositionTracker);
}
}
mService.mAnimator.removeDisplayLocked(mDisplayId);
// The pending transaction won't be applied so we should
// just clean up any surfaces pending destruction.
onPendingTransactionApplied();

View File

@@ -72,23 +72,29 @@ class SurfaceAnimator {
target.mInnerAnimationFinishedCallback.onAnimationFinished(anim);
return;
}
if (anim != mAnimation) {
// Callback was from another animation - ignore.
return;
}
final Transaction t = new Transaction();
SurfaceControl.openTransaction();
try {
reset(t, true /* destroyLeash */);
animationFinishedCallback.run();
} finally {
// TODO: This should use pendingTransaction eventually, but right now things
// happening on the animation finished callback are happening on the global
// transaction.
SurfaceControl.mergeToGlobalTransaction(t);
SurfaceControl.closeTransaction();
}
// TODO: This should use pendingTransaction eventually, but right now things
// happening on the animation finished callback are happening on the global
// transaction.
// For now we need to run this after it's guaranteed that the transaction that
// reparents the surface onto the leash is executed already. Otherwise this may be
// executed first, leading to surface loss, as the reparent operations wouldn't
// be in order.
mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
if (anim != mAnimation) {
// Callback was from another animation - ignore.
return;
}
final Transaction t = new Transaction();
SurfaceControl.openTransaction();
try {
reset(t, true /* destroyLeash */);
animationFinishedCallback.run();
} finally {
SurfaceControl.mergeToGlobalTransaction(t);
SurfaceControl.closeTransaction();
}
});
}
};
}

View File

@@ -35,6 +35,7 @@ import com.android.server.AnimationThread;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Singleton class that carries out the animations and Surface operations in a separate task
@@ -87,6 +88,12 @@ public class WindowAnimator {
*/
private boolean mAnimationFrameCallbackScheduled;
/**
* A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is
* executed and the corresponding transaction is closed and applied.
*/
private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
@@ -262,6 +269,7 @@ public class WindowAnimator {
mService.destroyPreservedSurfaceLocked();
mService.mWindowPlacerLocked.destroyPendingSurfaces();
executeAfterPrepareSurfacesRunnables();
if (DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating
@@ -425,4 +433,23 @@ public class WindowAnimator {
void orAnimating(boolean animating) {
mAnimating |= animating;
}
/**
* Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and
* the corresponding transaction is closed and applied.
*/
void addAfterPrepareSurfacesRunnable(Runnable r) {
mAfterPrepareSurfacesRunnables.add(r);
scheduleAnimation();
}
private void executeAfterPrepareSurfacesRunnables() {
// Traverse in order they were added.
final int size = mAfterPrepareSurfacesRunnables.size();
for (int i = 0; i < size; i++) {
mAfterPrepareSurfacesRunnables.get(i).run();
}
mAfterPrepareSurfacesRunnables.clear();
}
}

View File

@@ -45,6 +45,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
/**
* Test class for {@link SurfaceAnimatorTest}.
@@ -82,6 +83,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
callbackCaptor.getValue().onAnimationFinished(mSpec);
waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
@@ -104,11 +106,13 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
// First animation was finished, but this shouldn't cancel the second animation
callbackCaptor.getValue().onAnimationFinished(mSpec);
waitUntilPrepareSurfaces();
assertTrue(mAnimatable.mSurfaceAnimator.isAnimating());
// Second animation was finished
verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture());
callbackCaptor.getValue().onAnimationFinished(mSpec2);
waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable);
assertTrue(mAnimatable.mFinishedCallbackCalled);
}
@@ -160,6 +164,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash);
assertFalse(mAnimatable.mPendingDestroySurfaces.contains(leash));
callbackCaptor.getValue().onAnimationFinished(mSpec);
waitUntilPrepareSurfaces();
assertNotAnimating(mAnimatable2);
assertTrue(mAnimatable2.mFinishedCallbackCalled);
assertTrue(mAnimatable2.mPendingDestroySurfaces.contains(leash));
@@ -175,6 +180,14 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
assertNull(animatable.mSurfaceAnimator.getAnimation());
}
private void waitUntilPrepareSurfaces() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
synchronized (sWm.mWindowMap) {
sWm.mAnimator.addAfterPrepareSurfacesRunnable(latch::countDown);
}
latch.await();
}
private class MyAnimatable implements Animatable {
final SurfaceControl mParent;

View File

@@ -103,6 +103,7 @@ class WindowTestsBase {
context.getDisplay().getDisplayInfo(mDisplayInfo);
mDisplayContent = createNewDisplay();
sWm.mAnimator.mInitialized = true;
sWm.mDisplayEnabled = true;
sWm.mDisplayReady = true;