Merge "Fix back animation doesn't work when triggered a second time" into udc-dev
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 210c9aa..04f8477 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -561,6 +561,9 @@
}
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 @@
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 @@
*/
@VisibleForTesting
void onBackAnimationFinished() {
- if (!mPostCommitAnimationInProgress) {
- return;
- }
// Stop timeout runner.
mShellExecutor.removeCallbacks(mAnimationTimeoutRunnable);
mPostCommitAnimationInProgress = false;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 806bffe..0673484 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -166,6 +166,9 @@
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 @@
.setOnBackNavigationDone(new RemoteCallback(result)));
triggerBackGesture();
simulateRemoteAnimationStart(type);
+ mShellExecutor.flushAll();
+ releaseBackGesture();
simulateRemoteAnimationFinished();
mShellExecutor.flushAll();
@@ -252,6 +257,7 @@
createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, false);
triggerBackGesture();
+ releaseBackGesture();
verify(mAppCallback, times(1)).onBackInvoked();
@@ -269,6 +275,8 @@
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 @@
triggerBackGesture();
simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME);
+ mShellExecutor.flushAll();
+
+ releaseBackGesture();
// Simulate transition timeout.
mShellExecutor.flushAll();
@@ -369,6 +380,9 @@
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 @@
.setOnBackNavigationDone(new RemoteCallback(result)));
triggerBackGesture();
mShellExecutor.flushAll();
+ releaseBackGesture();
+ mShellExecutor.flushAll();
assertTrue("Navigation Done callback not called for "
+ BackNavigationInfo.typeToString(type), result.mBackNavigationDone);
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 7b562b0..7453743 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -648,31 +648,28 @@
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 @@
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 @@
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 @@
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;