Merge "Fix back animation doesn't work when triggered a second time" into udc-dev

This commit is contained in:
Arthur Hung
2023-04-11 09:31:07 +00:00
committed by Android (Google) Code Review
3 changed files with 45 additions and 19 deletions

View File

@@ -561,6 +561,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
if (runner.isWaitingAnimation()) {
ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
// Supposed it is in post commit animation state, and start the timeout to watch
// if the animation is ready.
mShellExecutor.executeDelayed(mAnimationTimeoutRunnable, MAX_ANIMATION_DURATION);
return;
} else if (runner.isAnimationCancelled()) {
invokeOrCancelBack();
@@ -577,6 +580,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (mPostCommitAnimationInProgress) {
return;
}
mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable);
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startPostCommitAnimation()");
mPostCommitAnimationInProgress = true;
mShellExecutor.executeDelayed(mAnimationTimeoutRunnable, MAX_ANIMATION_DURATION);
@@ -595,9 +600,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
*/
@VisibleForTesting
void onBackAnimationFinished() {
if (!mPostCommitAnimationInProgress) {
return;
}
// Stop timeout runner.
mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable);
mPostCommitAnimationInProgress = false;

View File

@@ -166,6 +166,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
doMotionEvent(MotionEvent.ACTION_MOVE, 0);
mController.setTriggerBack(true);
}
private void releaseBackGesture() {
doMotionEvent(MotionEvent.ACTION_UP, 0);
}
@@ -201,6 +204,8 @@ public class BackAnimationControllerTest extends ShellTestCase {
.setOnBackNavigationDone(new RemoteCallback(result)));
triggerBackGesture();
simulateRemoteAnimationStart(type);
mShellExecutor.flushAll();
releaseBackGesture();
simulateRemoteAnimationFinished();
mShellExecutor.flushAll();
@@ -252,6 +257,7 @@ public class BackAnimationControllerTest extends ShellTestCase {
createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, false);
triggerBackGesture();
releaseBackGesture();
verify(mAppCallback, times(1)).onBackInvoked();
@@ -269,6 +275,8 @@ public class BackAnimationControllerTest extends ShellTestCase {
triggerBackGesture();
simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME);
releaseBackGesture();
// Check that back invocation is dispatched.
verify(mAnimatorCallback).onBackInvoked();
verify(mBackAnimationRunner).onAnimationStart(anyInt(), any(), any(), any(), any());
@@ -308,6 +316,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
triggerBackGesture();
simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME);
mShellExecutor.flushAll();
releaseBackGesture();
// Simulate transition timeout.
mShellExecutor.flushAll();
@@ -369,6 +380,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
simulateRemoteAnimationStart(type);
mShellExecutor.flushAll();
releaseBackGesture();
mShellExecutor.flushAll();
assertTrue("Navigation Done callback not called for "
+ BackNavigationInfo.typeToString(type), result.mBackNavigationDone);
assertTrue("TriggerBack should have been true", result.mTriggerBack);
@@ -395,6 +409,8 @@ public class BackAnimationControllerTest extends ShellTestCase {
.setOnBackNavigationDone(new RemoteCallback(result)));
triggerBackGesture();
mShellExecutor.flushAll();
releaseBackGesture();
mShellExecutor.flushAll();
assertTrue("Navigation Done callback not called for "
+ BackNavigationInfo.typeToString(type), result.mBackNavigationDone);

View File

@@ -648,31 +648,28 @@ class BackNavigationController {
if (finishedTransition == mWaitTransitionFinish) {
clearBackAnimations();
}
if (!mBackAnimationInProgress || mPendingAnimationBuilder == null) {
return false;
}
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
"Handling the deferred animation after transition finished");
// Show the target surface and its parents to prevent it or its parents hidden when
// the transition finished.
// The target could be affected by transition when :
// Open transition -> the open target in back navigation
// Close transition -> the close target in back navigation.
// Find the participated container collected by transition when :
// Open transition -> the open target in back navigation, the close target in transition.
// Close transition -> the close target in back navigation, the open target in transition.
boolean hasTarget = false;
final SurfaceControl.Transaction t =
mPendingAnimationBuilder.mCloseTarget.getPendingTransaction();
for (int i = 0; i < targets.size(); i++) {
final WindowContainer wc = targets.get(i).mContainer;
if (wc.asActivityRecord() == null && wc.asTask() == null) {
continue;
} else if (!mPendingAnimationBuilder.containTarget(wc)) {
for (int i = 0; i < finishedTransition.mParticipants.size(); i++) {
final WindowContainer wc = finishedTransition.mParticipants.valueAt(i);
if (wc.asActivityRecord() == null && wc.asTask() == null
&& wc.asTaskFragment() == null) {
continue;
}
hasTarget = true;
t.show(wc.getSurfaceControl());
if (mPendingAnimationBuilder.containTarget(wc)) {
hasTarget = true;
break;
}
}
if (!hasTarget) {
@@ -689,6 +686,12 @@ class BackNavigationController {
return false;
}
// Ensure the final animation targets which hidden by transition could be visible.
for (int i = 0; i < targets.size(); i++) {
final WindowContainer wc = targets.get(i).mContainer;
wc.prepareSurfaces();
}
scheduleAnimation(mPendingAnimationBuilder);
mPendingAnimationBuilder = null;
return true;
@@ -1076,7 +1079,7 @@ class BackNavigationController {
boolean containTarget(@NonNull WindowContainer wc) {
return wc == mOpenTarget || wc == mCloseTarget
|| wc.hasChild(mOpenTarget) || wc.hasChild(mCloseTarget);
|| mOpenTarget.hasChild(wc) || mCloseTarget.hasChild(wc);
}
/**
@@ -1151,6 +1154,11 @@ class BackNavigationController {
private static void setLaunchBehind(@NonNull ActivityRecord activity) {
if (!activity.isVisibleRequested()) {
activity.setVisibility(true);
// The transition could commit the visibility and in the finishing state, that could
// skip commitVisibility call in setVisibility cause the activity won't visible here.
// Call it again to make sure the activity could be visible while handling the pending
// animation.
activity.commitVisibility(true, true);
}
activity.mLaunchTaskBehind = true;