Merge "Fix SurfaceAnimator and SurfaceAnimationRunner tests"

This commit is contained in:
Jorim Jaggi
2018-01-09 16:47:11 +00:00
committed by Android (Google) Code Review
8 changed files with 27 additions and 38 deletions

View File

@@ -49,7 +49,8 @@ class AppWindowThumbnail implements Animatable {
AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
mAppToken = appToken;
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService);
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
appToken.mService.mAnimator::addAfterPrepareSurfacesRunnable, appToken.mService);
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();

View File

@@ -30,6 +30,7 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.util.function.Consumer;
/**
* A class that can run animations on objects that have a set of child surfaces. We do this by
@@ -55,16 +56,20 @@ class SurfaceAnimator {
/**
* @param animatable The object to animate.
* @param animationFinishedCallback Callback to invoke when an animation has finished running.
* @param addAfterPrepareSurfaces Consumer that takes a runnable and executes it after preparing
* surfaces in WM. Can be implemented differently during testing.
*/
SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
WindowManagerService service) {
Consumer<Runnable> addAfterPrepareSurfaces, WindowManagerService service) {
mAnimatable = animatable;
mService = service;
mAnimationFinishedCallback = animationFinishedCallback;
mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback,
addAfterPrepareSurfaces);
}
private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback) {
private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback,
Consumer<Runnable> addAfterPrepareSurfaces) {
return anim -> {
synchronized (mService.mWindowMap) {
final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
@@ -80,7 +85,7 @@ class SurfaceAnimator {
// 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(() -> {
addAfterPrepareSurfaces.accept(() -> {
if (anim != mAnimation) {
// Callback was from another animation - ignore.
return;

View File

@@ -47,7 +47,6 @@ public class WindowAnimator {
final WindowManagerService mService;
final Context mContext;
final WindowManagerPolicy mPolicy;
private final WindowSurfacePlacer mWindowPlacerLocked;
/** Is any window animating? */
private boolean mAnimating;
@@ -74,7 +73,7 @@ public class WindowAnimator {
SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
boolean mInitialized = false;
private boolean mInitialized = false;
// When set to true the animator will go over all windows after an animation frame is posted and
// check if some got replaced and can be removed.
@@ -98,7 +97,6 @@ public class WindowAnimator {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
mWindowPlacerLocked = service.mWindowPlacerLocked;
AnimationThread.getHandler().runWithScissors(
() -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
@@ -241,7 +239,7 @@ public class WindowAnimator {
}
if (hasPendingLayoutChanges || doRequest) {
mWindowPlacerLocked.requestTraversal();
mService.mWindowPlacerLocked.requestTraversal();
}
final boolean rootAnimating = mService.mRoot.isSelfOrChildAnimating();
@@ -254,7 +252,7 @@ public class WindowAnimator {
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
if (!rootAnimating && mLastRootAnimating) {
mWindowPlacerLocked.requestTraversal();
mService.mWindowPlacerLocked.requestTraversal();
mService.mTaskSnapshotController.setPersisterPaused(false);
Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}

View File

@@ -102,7 +102,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
WindowContainer(WindowManagerService service) {
mService = service;
mPendingTransaction = service.mTransactionFactory.make();
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
service.mAnimator::addAfterPrepareSurfacesRunnable, service);
}
@Override

View File

@@ -928,7 +928,6 @@ public class WindowManagerService extends IWindowManager.Stub
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
installLock(this, INDEX_WINDOW);
mRoot = new RootWindowContainer(this);
mContext = context;
mHaveInputMethods = haveInputMethods;
mAllowBootMessages = showBootMsgs;
@@ -952,8 +951,11 @@ public class WindowManagerService extends IWindowManager.Stub
mDisplaySettings = new DisplaySettings();
mDisplaySettings.readSettingsLocked();
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mPolicy = policy;
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);
@@ -1051,7 +1053,6 @@ public class WindowManagerService extends IWindowManager.Stub
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
mAnimator = new WindowAnimator(this);
mSurfaceAnimationRunner = new SurfaceAnimationRunner();
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(

View File

@@ -37,6 +37,7 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
import android.view.SurfaceControl;
@@ -159,8 +160,12 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase {
when(mMockAnimationSpec.getDuration()).thenReturn(200L);
mSurfaceAnimationRunner.startAnimation(mMockAnimationSpec, mMockSurface, mMockTransaction,
this::finishedCallback);
// We need to wait for two frames: The first frame starts the animation, the second frame
// actually cancels the animation.
waitUntilNextFrame();
assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
waitUntilNextFrame();
assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty());
verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L));
}

View File

@@ -75,10 +75,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
mAnimatable2 = new MyAnimatable();
}
// TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
// mark them as ignore.
@Test
@Ignore
public void testRunAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
@@ -88,17 +85,13 @@ 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));
// TODO: Verify reparenting once we use mPendingTransaction to reparent it back
}
// TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
// mark them as ignore.
@Test
@Ignore
public void testOverrideAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
final SurfaceControl firstLeash = mAnimatable.mLeash;
@@ -114,13 +107,11 @@ 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);
}
@@ -157,10 +148,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
}
// TODO: Tests are flaky, and timeout after 5 minutes. Instead of wasting everybody's time we
// mark them as ignore.
@Test
@Ignore
public void testTransferAnimation() throws Exception {
mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
@@ -175,7 +163,6 @@ 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));
@@ -191,14 +178,6 @@ 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;
@@ -219,7 +198,7 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
.build();
mFinishedCallbackCalled = false;
mLeash = null;
mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm);
mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, Runnable::run, sWm);
}
@Override

View File

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