From 23ffbdb7a8794a2269721cf86bb5823b29a039ff Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 8 Feb 2022 16:25:29 +0800 Subject: [PATCH] Replace mPendingRemove with hierarchy deferred removal To eliminate the global list and simplify the path of surface placement. This reverts commit 4ddb1d869c70a2e0c837c9ac8b0fac280299cb6f. Reason for revert: Fix the original CL (commit bb2efa0) by checking "!isSelfAnimating(0 /* flags */, EXIT_ANIMATING_TYPES)" in WindowState#handleCompleteDeferredRemoval. Bug: 163976519 Test: WindowContainerTests#testHandleCompleteDeferredRemoval Test: Long press power key and dismiss the power menu window. The window should have fade out animation. Change-Id: I9bd75a82952ef129f528a0dba8fe740eddf60c49 --- .../server/wm/RootWindowContainer.java | 23 ------------- .../server/wm/WindowManagerService.java | 33 ------------------- .../com/android/server/wm/WindowState.java | 13 +++++--- .../server/wm/WindowContainerTests.java | 18 ++++++++++ 4 files changed, 27 insertions(+), 60 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index ee03d02791ff8..76a7981fa946e 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -981,29 +981,6 @@ class RootWindowContainer extends WindowContainer mWmService.checkDrawnWindowsLocked(); } - final int N = mWmService.mPendingRemove.size(); - if (N > 0) { - if (mWmService.mPendingRemoveTmp.length < N) { - mWmService.mPendingRemoveTmp = new WindowState[N + 10]; - } - mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp); - mWmService.mPendingRemove.clear(); - ArrayList displayList = new ArrayList(); - for (i = 0; i < N; i++) { - final WindowState w = mWmService.mPendingRemoveTmp[i]; - w.removeImmediately(); - final DisplayContent displayContent = w.getDisplayContent(); - if (displayContent != null && !displayList.contains(displayContent)) { - displayList.add(displayContent); - } - } - - for (int j = displayList.size() - 1; j >= 0; --j) { - final DisplayContent dc = displayList.get(j); - dc.assignWindowLayers(true /*setLayoutNeeded*/); - } - } - forAllDisplays(dc -> { dc.getInputMonitor().updateInputWindowsLw(true /*force*/); dc.updateSystemGestureExclusion(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c9c3f1da5b405..71f48824b9e4c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -224,7 +224,6 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.MergedConfiguration; import android.util.Slog; -import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.TypedValue; @@ -583,20 +582,6 @@ public class WindowManagerService extends IWindowManager.Stub */ final ArrayList mResizingWindows = new ArrayList<>(); - /** - * Windows whose animations have ended and now must be removed. - */ - final ArrayList mPendingRemove = new ArrayList<>(); - - /** - * Used when processing mPendingRemove to avoid working on the original array. - */ - WindowState[] mPendingRemoveTmp = new WindowState[20]; - - // TODO: use WindowProcessController once go/wm-unified is done. - /** Mapping of process pids to configurations */ - final SparseArray mProcessConfigurations = new SparseArray<>(); - /** * Mapping of displayId to {@link DisplayImePolicy}. * Note that this can be accessed without holding the lock. @@ -2039,7 +2024,6 @@ public class WindowManagerService extends IWindowManager.Stub dc.mWinRemovedSinceNullFocus.add(win); } mEmbeddedWindowController.onWindowRemoved(win); - mPendingRemove.remove(win); mResizingWindows.remove(win); updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */); mWindowsChanged = true; @@ -6411,23 +6395,6 @@ public class WindowManagerService extends IWindowManager.Stub } } } - if (mPendingRemove.size() > 0) { - pw.println(); - pw.println(" Remove pending for:"); - for (int i=mPendingRemove.size()-1; i>=0; i--) { - WindowState w = mPendingRemove.get(i); - if (windows == null || windows.contains(w)) { - pw.print(" Remove #"); pw.print(i); pw.print(' '); - pw.print(w); - if (dumpAll) { - pw.println(":"); - w.dump(pw, " ", true); - } else { - pw.println(); - } - } - } - } if (mForceRemoves != null && mForceRemoves.size() > 0) { pw.println(); pw.println(" Windows force removing:"); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 0d72e9a567bcd..11a6141c6c6d0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4910,15 +4910,20 @@ class WindowState extends WindowContainer implements WindowManagerP if (hasSurface) { mWmService.mDestroySurface.add(this); } - if (mRemoveOnExit) { - mWmService.mPendingRemove.add(this); - mRemoveOnExit = false; - } } mAnimatingExit = false; getDisplayContent().mWallpaperController.hideWallpapers(this); } + @Override + boolean handleCompleteDeferredRemoval() { + if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, EXIT_ANIMATING_TYPES)) { + mRemoveOnExit = false; + removeImmediately(); + } + return super.handleCompleteDeferredRemoval(); + } + boolean clearAnimatingFlags() { boolean didSomething = false; // We don't want to clear it out for windows that get replaced, because the diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index 8b14e981f046a..41a59eb30246a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -870,6 +870,24 @@ public class WindowContainerTests extends WindowTestsBase { final DisplayContent displayContent = createNewDisplay(); // Do not reparent activity to default display when removing the display. doReturn(true).when(displayContent).shouldDestroyContentOnRemove(); + + // An animating window with mRemoveOnExit can be removed by handleCompleteDeferredRemoval + // once it no longer animates. + final WindowState exitingWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, + displayContent, "exiting window"); + exitingWindow.startAnimation(exitingWindow.getPendingTransaction(), + mock(AnimationAdapter.class), false /* hidden */, + SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION); + exitingWindow.mRemoveOnExit = true; + exitingWindow.handleCompleteDeferredRemoval(); + // The animation has not finished so the window is not removed. + assertTrue(exitingWindow.isAnimating()); + assertTrue(exitingWindow.isAttached()); + exitingWindow.cancelAnimation(); + // The window is removed because the animation is gone. + exitingWindow.handleCompleteDeferredRemoval(); + assertFalse(exitingWindow.isAttached()); + final ActivityRecord r = new TaskBuilder(mSupervisor).setCreateActivity(true) .setDisplay(displayContent).build().getTopMostActivity(); // Add a window and make the activity animating so the removal of activity is deferred.