From ca274ed00625acd6df17710f0fc4bd4b6e665122 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Tue, 5 May 2020 17:32:21 +0800 Subject: [PATCH] Allow apply animation to ActivityRecord after transfer starting window. If there are two activities be start continuous, it might have a chance that opening transition cannot be applied becuase the starting window just been transferred to secondary activity. To fix this, only set mUseTransferredAnimation to true when the first ActivityRecord is animating. Bug: 155030898 Test: atest TaskSnapshotControllerTest AppWindowTokenTests Test: atest AppWindowTokenTests#testTransferStartingWindowCanAnimate Change-Id: I09166094514a5867e24e8421e0c829dd7446b123 --- .../com/android/server/wm/ActivityRecord.java | 14 ++++++---- .../server/wm/AppWindowTokenTests.java | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 0dbc9155757ea..16b65f24e7087 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -571,7 +571,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults = new WindowState.UpdateReportedVisibilityResults(); - boolean mUseTransferredAnimation; + private boolean mUseTransferredAnimation; /** * @see #currentLaunchCanTurnScreenOn() @@ -3373,12 +3373,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } setClientVisible(fromActivity.mClientVisible); - transferAnimation(fromActivity); + if (fromActivity.isAnimating()) { + transferAnimation(fromActivity); - // When transferring an animation, we no longer need to apply an animation to the - // the token we transfer the animation over. Thus, set this flag to indicate we've - // transferred the animation. - mUseTransferredAnimation = true; + // When transferring an animation, we no longer need to apply an animation to + // the token we transfer the animation over. Thus, set this flag to indicate + // we've transferred the animation. + mUseTransferredAnimation = true; + } mWmService.updateFocusedWindowLocked( UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index cf3cfecbf65e3..5c21853b1f598 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -31,10 +31,12 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; @@ -59,6 +61,8 @@ import android.view.WindowManager; import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; +import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -365,6 +369,30 @@ public class AppWindowTokenTests extends WindowTestsBase { assertHasStartingWindow(activity2); } + @Test + public void testTransferStartingWindowCanAnimate() { + final ActivityRecord activity1 = createIsolatedTestActivityRecord(); + final ActivityRecord activity2 = createIsolatedTestActivityRecord(); + activity1.addStartingWindow(mPackageName, + android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, + false, false); + waitUntilHandlersIdle(); + activity2.addStartingWindow(mPackageName, + android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(), + true, true, false, true, false, false); + waitUntilHandlersIdle(); + assertNoStartingWindow(activity1); + assertHasStartingWindow(activity2); + + // Assert that bottom activity is allowed to do animation. + doReturn(true).when(activity2).okToAnimate(); + doReturn(true).when(activity2).isAnimating(); + final OnAnimationFinishedCallback onAnimationFinishedCallback = + mock(OnAnimationFinishedCallback.class); + assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false, + onAnimationFinishedCallback)); + } + private ActivityRecord createIsolatedTestActivityRecord() { final ActivityStack taskStack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(taskStack, 0 /* userId */);