Cancel pending animation when state changed.
The participants of pending animation were cached while another
transition playing, so when a transition finish, the participant target
could already changed or removed. We can use NavigationMonitor to
cancel the pending animation if the target has changed.
Bug: 277663454
Test: manual, try to verify the pending animation shouldn't start when
navigation window has changed.
Change-Id: I4db578bd46932549afe5f3cb7f2e0f147bbf1a82
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 7b562b0..efde703 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -532,14 +532,7 @@
if (newFocus != null && newFocus != mNavigatingWindow
&& (newFocus.mActivityRecord == null
|| (newFocus.mActivityRecord == mNavigatingWindow.mActivityRecord))) {
- EventLogTags.writeWmBackNaviCanceled("focusWindowChanged");
- if (isMonitorForRemote()) {
- mObserver.sendResult(null /* result */);
- }
- if (isMonitorAnimationOrTransition()) {
- // transition won't happen, cancel internal status
- clearBackAnimations();
- }
+ cancelBackNavigating("focusWindowChanged");
}
}
@@ -553,19 +546,12 @@
}
final ArrayList<WindowContainer> all = new ArrayList<>(opening);
all.addAll(closing);
- for (WindowContainer app : all) {
- if (app.hasChild(mNavigatingWindow)) {
- EventLogTags.writeWmBackNaviCanceled("transitionHappens");
- if (isMonitorForRemote()) {
- mObserver.sendResult(null /* result */);
- }
- if (isMonitorAnimationOrTransition()) {
- clearBackAnimations();
- }
+ for (int i = all.size() - 1; i >= 0; --i) {
+ if (all.get(i).hasChild(mNavigatingWindow)) {
+ cancelBackNavigating("transitionHappens");
break;
}
}
-
}
private boolean atSameDisplay(WindowState newFocus) {
@@ -575,6 +561,17 @@
final int navigatingDisplayId = mNavigatingWindow.getDisplayId();
return newFocus == null || newFocus.getDisplayId() == navigatingDisplayId;
}
+
+ private void cancelBackNavigating(String reason) {
+ EventLogTags.writeWmBackNaviCanceled(reason);
+ if (isMonitorForRemote()) {
+ mObserver.sendResult(null /* result */);
+ }
+ if (isMonitorAnimationOrTransition()) {
+ clearBackAnimations();
+ }
+ cancelPendingAnimation();
+ }
}
// For shell transition
@@ -680,12 +677,7 @@
Slog.w(TAG, "Finished transition didn't include the targets"
+ " open: " + mPendingAnimationBuilder.mOpenTarget
+ " close: " + mPendingAnimationBuilder.mCloseTarget);
- try {
- mPendingAnimationBuilder.mBackAnimationAdapter.getRunner().onAnimationCancelled();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- mPendingAnimationBuilder = null;
+ cancelPendingAnimation();
return false;
}
@@ -694,6 +686,18 @@
return true;
}
+ private void cancelPendingAnimation() {
+ if (mPendingAnimationBuilder == null) {
+ return;
+ }
+ try {
+ mPendingAnimationBuilder.mBackAnimationAdapter.getRunner().onAnimationCancelled();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote animation gone", e);
+ }
+ mPendingAnimationBuilder = null;
+ }
+
/**
* Create and handling animations status for an open/close animation targets.
*/