From fe0dfcbe2a15e350c25c252228329b84c58ad83c Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Mon, 2 Sep 2019 15:59:38 +0800 Subject: [PATCH 1/2] Fix two activity stack leak cases 1) An activity stack was created while starting an activity. The stack should be destroyed if activity did not landed on the stack eventually. 2) Recent stack shouldn't be created if the recents component is also the home activity, while showing Recents in split-screen. Bug: 137232340 Test: atest ActivityStarterTests ActivityVisibilityTests Change-Id: Id870bc5249cd98b891ee7e6a1968f1ee2c6060fd --- .../core/java/com/android/server/wm/ActivityStack.java | 9 +++++---- .../core/java/com/android/server/wm/ActivityStarter.java | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index a8eaaa4c2438a..a09d3c8fc4f2d 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -834,11 +834,12 @@ class ActivityStack extends ConfigurationContainer { // so that the divider matches and remove this logic. // TODO: This is currently only called when entering split-screen while in another // task, and from the tests - // TODO (b/78247419): Check if launcher and overview are same then move home stack - // instead of recents stack. Then fix the rotation animation from fullscreen to - // minimized mode + // TODO (b/78247419): Fix the rotation animation from fullscreen to minimized mode + final boolean isRecentsComponentHome = + mService.getRecentTasks().isRecentsComponentHomeActivity(mCurrentUser); final ActivityStack recentStack = display.getOrCreateStack( - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS, + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, + isRecentsComponentHome ? ACTIVITY_TYPE_HOME : ACTIVITY_TYPE_RECENTS, true /* onTop */); recentStack.moveToFront("setWindowingMode"); // If task moved to docked stack - show recents if needed. diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5717e2fa02d25..66ebe097695bf 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2337,7 +2337,12 @@ class ActivityStarter { REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME, "reparentingHome"); mMovedToFront = true; + } else if (launchStack.topTask() == null) { + // The task does not need to be reparented to the launch stack. Remove the + // launch stack if there is no activity in it. + launchStack.remove(); } + mOptions = null; // We are moving a task to the front, use starting window to hide initial drawn From a5d070e689106544c36b5864938599aa60ee290b Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Wed, 4 Sep 2019 13:20:01 +0800 Subject: [PATCH 2/2] Fix ReplaceWindowTests#testReplaceWindow_Dock_Relaunch() failure Window was destroyed and added back when activity relaunched while being moved from fullscreen stack to split-screen primary stack. The activity window was recreated during the relaunch process because RAC#ensureActivitiesVisible() executed recursively and the inner calls override the setting to not preserve windows. Avoid running RAC#ensureActivitiesVisible() recursively. RootActivityContainer#ensureActivitiesVisible() RootActivityContainer#ensureActivitiesVisible(preserveWindows=false) ActivityTaskManagerService#ensureConfigAndVisibilityAfterUpdate() ActivityDisplay#updateDisplayOverrideConfigurationLocked() RootActivityContainer#ensureVisibilityAndConfig() ActivityStack#resumeTopActivityInnerLocked() ActivityStack#resumeTopActivityUncheckedLocked() ActivityRecord#makeActiveIfNeeded() ActivityRecord#makeClientVisible() ActivityRecord#makeVisibleIfNeeded() ActivityStack#ensureActivitiesVisibleLocked() ActivityDisplay#ensureActivitiesVisible() RootActivityContainer#ensureActivitiesVisible() RootActivityContainer#ensureActivitiesVisible(preserveWindows=true) ActivityStack#setWindowingModeInSurfaceTransaction() ActivityStack#lambda$setWindowingMode$0$ActivityStack() WindowManagerService#inSurfaceTransaction() ActivityStack#setWindowingMode() ActivityTaskManagerService#setTaskWindowingModeSplitScreenPrimary() ActivityTaskManagerService#setTaskWindowingMode() Bug: 137232340 Test: atest ReplaceWindowTests Change-Id: I8243a49edf8314100e13d3a15b961e3d768f6364 --- .../com/android/server/wm/RootActivityContainer.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index eb5d096aa781e..c1642f084b25e 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -196,6 +196,9 @@ class RootActivityContainer extends ConfigurationContainer /** Set when a power hint has started, but not ended. */ private boolean mPowerHintSent; + /** Used to keep ensureActivitiesVisible() from being entered recursively. */ + private boolean mInEnsureActivitiesVisible = false; + // The default minimal size that will be used if the activity doesn't specify its minimal size. // It will be calculated when the default display gets added. int mDefaultMinSizeOfResizeableTaskDp = -1; @@ -808,8 +811,14 @@ class RootActivityContainer extends ConfigurationContainer */ void ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { - mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate(); + if (mInEnsureActivitiesVisible) { + // Don't do recursive work. + return; + } + mInEnsureActivitiesVisible = true; + try { + mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate(); // First the front stacks. In case any are not fullscreen and are in front of home. for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.get(displayNdx); @@ -818,6 +827,7 @@ class RootActivityContainer extends ConfigurationContainer } } finally { mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate(); + mInEnsureActivitiesVisible = false; } }