Clean-up change transition when cancelled before anim starts
Change transitions require the app window be put in an interim
state while waiting for the end-state snapshot and animation
to start. when moving an app from one display to another, it
gets a config/mode change before onDisplayChanged causing it
to prepare for an animation that never happens.
This change cleans-up the pending-change-transition state in
the various cases where the animation is cancelled before it
has started.
Bug: 120034483
Test: create simulated display in desktop mode, launch freeform app
on it, remove display. App is now visible.
Added more AppChangeTransitionTests for these cases.
Change-Id: I14a758957903ff7b3efd286f713f81b9de293fcb
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2cc85e2..bcf6aba 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1275,7 +1275,19 @@
void onDisplayChanged(DisplayContent dc) {
DisplayContent prevDc = mDisplayContent;
super.onDisplayChanged(dc);
- if (prevDc != null && prevDc.mFocusedApp == this) {
+ if (prevDc == null) {
+ return;
+ }
+ if (prevDc.mChangingApps.contains(this)) {
+ // This gets called *after* the AppWindowToken has been reparented to the new display.
+ // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
+ // so this token is now "frozen" while waiting for the animation to start on prevDc
+ // (which will be cancelled since the window is no-longer a child). However, since this
+ // is no longer a child of prevDc, this won't be notified of the cancelled animation,
+ // so we need to cancel the change transition here.
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
+ }
+ if (prevDc.mFocusedApp == this) {
prevDc.setFocusedApp(null);
final TaskStack stack = dc.getTopStack();
if (stack != null) {
@@ -1584,7 +1596,10 @@
}
private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
- if (!isVisible() || getDisplayContent().mAppTransition.isTransitionSet()) {
+ if (mWmService.mDisableTransitionAnimation
+ || !isVisible()
+ || getDisplayContent().mAppTransition.isTransitionSet()
+ || getSurfaceControl() == null) {
return false;
}
// Only do an animation into and out-of freeform mode for now. Other mode
@@ -2561,9 +2576,7 @@
return;
} else if (mTransitChangeLeash != null) {
// unparent mTransitChangeLeash for clean-up
- t.hide(mTransitChangeLeash);
- t.reparent(mTransitChangeLeash, null);
- mTransitChangeLeash = null;
+ clearChangeLeash(t, false /* cancel */);
}
if (mAnimatingAppWindowTokenRegistry != null) {
@@ -2659,15 +2672,36 @@
return super.isSelfAnimating();
}
+ /**
+ * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
+ * to another leash.
+ */
+ private void clearChangeLeash(Transaction t, boolean cancel) {
+ if (mTransitChangeLeash == null) {
+ return;
+ }
+ if (cancel) {
+ clearThumbnail();
+ SurfaceControl sc = getSurfaceControl();
+ SurfaceControl parentSc = getParentSurfaceControl();
+ // Don't reparent if surface is getting destroyed
+ if (parentSc != null && sc != null) {
+ t.reparent(sc, getParentSurfaceControl());
+ }
+ }
+ t.hide(mTransitChangeLeash);
+ t.reparent(mTransitChangeLeash, null);
+ mTransitChangeLeash = null;
+ if (cancel) {
+ onAnimationLeashDestroyed(t);
+ }
+ }
+
@Override
void cancelAnimation() {
cancelAnimationOnly();
clearThumbnail();
- if (mTransitChangeLeash != null) {
- getPendingTransaction().hide(mTransitChangeLeash);
- getPendingTransaction().reparent(mTransitChangeLeash, null);
- mTransitChangeLeash = null;
- }
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
}
/**
@@ -3003,7 +3037,9 @@
void removeFromPendingTransition() {
if (isWaitingForTransitionStart() && mDisplayContent != null) {
mDisplayContent.mOpeningApps.remove(this);
- mDisplayContent.mChangingApps.remove(this);
+ if (mDisplayContent.mChangingApps.remove(this)) {
+ clearChangeLeash(getPendingTransaction(), true /* cancel */);
+ }
mDisplayContent.mClosingApps.remove(this);
}
}