From 3c1c2c04e2dde3ac9e7f92af63ab24a4f180330f Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Tue, 23 Jun 2020 17:18:54 +0800 Subject: [PATCH] Fix the regression that closing transition disappeared. For hierarchical animation, there are missing some handling around mNeedsZBoost, when closing an activity the transition did not applied. 1. Move some codes around mNeedsZBoost from ActivityRecord to WindowContainer so Task can also benefit from it. 2. TaskDisplayArea#assignChildLayers should combined needsZBoost so this attribute can apply on root task. 3. If next top activity will move to top in #finishIfPossible and the finishing activity is on top, provide it a higher layer to remain on top. Otherwise user will see flicker because the transition need to be applied until next activity resumed. Bug: 159200318 Test: atest ActivityRecordTests TaskDisplayAreaTests AppWindowTokenAnimationTests TransitionSelectionTests Change-Id: I85ec3307b31444e09179abca30298af2ce538834 --- .../com/android/server/wm/ActivityRecord.java | 12 ++- .../android/server/wm/TaskDisplayArea.java | 83 ++++++++++++++----- .../android/server/wm/WindowContainer.java | 1 + 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2e9f704484886..71f89426eb0a0 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2560,7 +2560,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mayAdjustTop && ((ActivityStack) task).topRunningActivity(true /* focusableOnly */) == null) { task.adjustFocusToNextFocusableTask("finish-top", false /* allowFocusSelf */, - shouldAdjustGlobalFocus); + shouldAdjustGlobalFocus); } finishActivityResults(resultCode, resultData, resultGrants); @@ -2580,7 +2580,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (DEBUG_VISIBILITY || DEBUG_TRANSITION) { Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this); } - getDisplay().mDisplayContent.prepareAppTransition(transit, false); + mDisplayContent.prepareAppTransition(transit, false); // When finishing the activity preemptively take the snapshot before the app window // is marked as hidden and any configuration changes take place @@ -2605,6 +2605,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (endTask) { mAtmService.getLockTaskController().clearLockedTask(task); + // This activity was in the top focused stack and this is the last activity in + // that task, give this activity a higher layer so it can stay on top before the + // closing task transition be executed. + if (mayAdjustTop) { + mNeedsZBoost = true; + mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */); + } } } else if (!isState(PAUSING)) { if (mVisibleRequested) { @@ -6105,7 +6112,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished"); mTransit = TRANSIT_UNSET; mTransitFlags = 0; - mNeedsZBoost = false; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 205a8d2aeeac0..c3acb16dda49f 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -52,6 +52,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.os.UserHandle; +import android.util.IntArray; import android.util.Slog; import android.view.SurfaceControl; import android.window.WindowContainerTransaction; @@ -106,6 +107,9 @@ final class TaskDisplayArea extends DisplayArea { private final ArrayList mTmpAlwaysOnTopStacks = new ArrayList<>(); private final ArrayList mTmpNormalStacks = new ArrayList<>(); private final ArrayList mTmpHomeStacks = new ArrayList<>(); + private final IntArray mTmpNeedsZBoostIndexes = new IntArray(); + private int mTmpLayerForSplitScreenDividerAnchor; + private int mTmpLayerForAnimationLayer; private ArrayList mTmpTasks = new ArrayList<>(); @@ -633,39 +637,72 @@ final class TaskDisplayArea extends DisplayArea { int layer = 0; // Place home stacks to the bottom. - for (int i = 0; i < mTmpHomeStacks.size(); i++) { - mTmpHomeStacks.get(i).assignLayer(t, layer++); - } + layer = adjustRootTaskLayer(t, mTmpHomeStacks, layer, false /* normalStacks */); // The home animation layer is between the home stacks and the normal stacks. final int layerForHomeAnimationLayer = layer++; - int layerForSplitScreenDividerAnchor = layer++; - int layerForAnimationLayer = layer++; - for (int i = 0; i < mTmpNormalStacks.size(); i++) { - final ActivityStack s = mTmpNormalStacks.get(i); - s.assignLayer(t, layer++); - if (s.inSplitScreenWindowingMode()) { - // The split screen divider anchor is located above the split screen window. - layerForSplitScreenDividerAnchor = layer++; - } - if (s.isTaskAnimating() || s.isAppTransitioning()) { - // The animation layer is located above the highest animating stack and no - // higher. - layerForAnimationLayer = layer++; - } - } + mTmpLayerForSplitScreenDividerAnchor = layer++; + mTmpLayerForAnimationLayer = layer++; + layer = adjustRootTaskLayer(t, mTmpNormalStacks, layer, true /* normalStacks */); + // The boosted animation layer is between the normal stacks and the always on top // stacks. final int layerForBoostedAnimationLayer = layer++; - for (int i = 0; i < mTmpAlwaysOnTopStacks.size(); i++) { - mTmpAlwaysOnTopStacks.get(i).assignLayer(t, layer++); - } + adjustRootTaskLayer(t, mTmpAlwaysOnTopStacks, layer, false /* normalStacks */); t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer); - t.setLayer(mAppAnimationLayer, layerForAnimationLayer); - t.setLayer(mSplitScreenDividerAnchor, layerForSplitScreenDividerAnchor); + t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer); + t.setLayer(mSplitScreenDividerAnchor, mTmpLayerForSplitScreenDividerAnchor); t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer); } + private int adjustNormalStackLayer(ActivityStack s, int layer) { + if (s.inSplitScreenWindowingMode()) { + // The split screen divider anchor is located above the split screen window. + mTmpLayerForSplitScreenDividerAnchor = layer++; + } + if (s.isTaskAnimating() || s.isAppTransitioning()) { + // The animation layer is located above the highest animating stack and no + // higher. + mTmpLayerForAnimationLayer = layer++; + } + return layer; + } + + /** + * Adjusts the layer of the stack which belongs to the same group. + * Note that there are three stack groups: home stacks, always on top stacks, and normal stacks. + * + * @param startLayer The beginning layer of this group of stacks. + * @param normalStacks Set {@code true} if this group is neither home nor always on top. + * @return The adjusted layer value. + */ + private int adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList stacks, + int startLayer, boolean normalStacks) { + mTmpNeedsZBoostIndexes.clear(); + final int stackSize = stacks.size(); + for (int i = 0; i < stackSize; i++) { + final ActivityStack stack = stacks.get(i); + if (!stack.needsZBoost()) { + stack.assignLayer(t, startLayer++); + if (normalStacks) { + startLayer = adjustNormalStackLayer(stack, startLayer); + } + } else { + mTmpNeedsZBoostIndexes.add(i); + } + } + + final int zBoostSize = mTmpNeedsZBoostIndexes.size(); + for (int i = 0; i < zBoostSize; i++) { + final ActivityStack stack = stacks.get(mTmpNeedsZBoostIndexes.get(i)); + stack.assignLayer(t, startLayer++); + if (normalStacks) { + startLayer = adjustNormalStackLayer(stack, startLayer); + } + } + return startLayer; + } + @Override SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) { switch (animationLayer) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 5a73fabaf9d06..f984a8b024c14 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2440,6 +2440,7 @@ class WindowContainer extends ConfigurationContainer< protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { doAnimationFinished(type, anim); mWmService.onAnimationFinished(); + mNeedsZBoost = false; } /**