From edc429403d7202a8948311f3e18e4c4f3a5eeae6 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Mon, 12 Apr 2021 12:22:14 +0800 Subject: [PATCH] Handle stopping and finishing activities on drawn If the non idle activity is started in a new task, there may have a starting window. So the transition animation can be done with the starting window but the main window of the activity may not finish drawing if it is slow during startup. That causes the allResumedActivitiesVisible to return false and the stopping activities are still pending. By scheduling to process stopping and finishing when the activity windows are actually drawn (though its name is onWindowsVisible, it is only called if the windows are drawn, see numVisible), the pending stopping activities no longer need to wait until idle timeout to be stopped or destroyed. Also avoid sending duplicated idle message. Bug: 169740664 Test: atest ActivityVisibilityTests# \ testActivityStoppedWhileNextActivityNotIdle Change-Id: I7317bf577a1b98601b6ec027a5d7bf66090aecde --- .../com/android/server/wm/ActivityRecord.java | 25 +++++++------------ .../server/wm/ActivityTaskSupervisor.java | 10 +++++--- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 5b4e6a0320509..444835ab960dc 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5862,6 +5862,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A nowVisible = true; lastVisibleTime = SystemClock.uptimeMillis(); mAtmService.scheduleAppGcsLocked(); + // The nowVisible may be false in onAnimationFinished because the transition animation + // was started by starting window but the main window hasn't drawn so the procedure + // didn't schedule. Hence also check when nowVisible becomes true (drawn) to avoid the + // closing activity having to wait until idle timeout to be stopped or destroyed if the + // next activity won't report idle (e.g. repeated view animation). + mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded(); } } @@ -6682,22 +6688,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token); scheduleAnimation(); - if (!mTaskSupervisor.mStoppingActivities.isEmpty() - || !mTaskSupervisor.mFinishingActivities.isEmpty()) { - if (mRootWindowContainer.allResumedActivitiesIdle()) { - // If all activities are already idle then we now need to make sure we perform - // the full stop of this activity. This is because we won't do that while they - // are still waiting for the animation to finish. - mTaskSupervisor.scheduleIdle(); - } else if (mRootWindowContainer.allResumedActivitiesVisible()) { - // If all resumed activities are already visible (and should be drawn, see - // updateReportedVisibility ~ nowVisible) but not idle, we still schedule to - // process the stopping and finishing activities because the transition is done. - // This also avoids if the next activity never reports idle (e.g. animating view), - // the previous will need to wait until idle timeout to be stopped or destroyed. - mTaskSupervisor.scheduleProcessStoppingAndFinishingActivities(); - } - } + // Schedule to handle the stopping and finishing activities which the animation is done + // because the activities which were animating have not been stopped yet. + mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index bdde3692ef534..2b1cf395dcd7d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2027,7 +2027,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } final void scheduleIdle() { - mHandler.sendEmptyMessage(IDLE_NOW_MSG); + if (!mHandler.hasMessages(IDLE_NOW_MSG)) { + mHandler.sendEmptyMessage(IDLE_NOW_MSG); + } } /** @@ -2115,8 +2117,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } } - void scheduleProcessStoppingAndFinishingActivities() { - if (!mHandler.hasMessages(PROCESS_STOPPING_AND_FINISHING_MSG)) { + void scheduleProcessStoppingAndFinishingActivitiesIfNeeded() { + if ((!mStoppingActivities.isEmpty() || !mFinishingActivities.isEmpty()) + && !mHandler.hasMessages(PROCESS_STOPPING_AND_FINISHING_MSG) + && mRootWindowContainer.allResumedActivitiesVisible()) { mHandler.sendEmptyMessage(PROCESS_STOPPING_AND_FINISHING_MSG); } }