diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 8bedeae03ad40..cf37bb5e5192d 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4861,8 +4861,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void stopIfPossible() { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this); final ActivityStack stack = getActivityStack(); - if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 - || (info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0) { + if (isNoHistory()) { if (!finishing) { if (!stack.shouldSleepActivities()) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this); @@ -6094,20 +6093,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token); scheduleAnimation(); - if (mAtmService.mRootWindowContainer.allResumedActivitiesIdle() - || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) { - // If all activities are already idle or there is an activity that must be - // stopped immediately after visible, 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. - if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) { + if (!mStackSupervisor.mStoppingActivities.isEmpty() + || !mStackSupervisor.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. mStackSupervisor.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. + mStackSupervisor.scheduleProcessStoppingAndFinishingActivities(); + } else { + // Instead of doing the full stop routine here, let's just hide any activities + // we now can, and let them stop when the normal idle happens. + mStackSupervisor.processStoppingActivities(null /* launchedActivity */, + true /* onlyUpdateVisibility */, true /* unused */, null /* unused */); } - } else { - // Instead of doing the full stop routine here, let's just hide any activities - // we now can, and let them stop when the normal idle happens. - mStackSupervisor.processStoppingActivities(null /* launchedActivity */, - true /* onlyUpdateVisibility */, true /* unused */, null /* unused */); } Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index ef34327597bc7..814cb451edd29 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -1414,8 +1414,7 @@ class ActivityStack extends WindowContainer implements BoundsAn else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev); mPausingActivity = prev; mLastPausedActivity = prev; - mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 - || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null; + mLastNoHistoryActivity = prev.isNoHistory() ? prev : null; prev.setState(PAUSING, "startPausingLocked"); prev.getTask().touchActiveTime(); clearLaunchTime(prev); diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index ed7394378dc64..e8564fc80ac37 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -183,6 +183,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2; private static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3; private static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4; + private static final int PROCESS_STOPPING_AND_FINISHING_MSG = FIRST_SUPERVISOR_STACK_MSG + 5; private static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12; private static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 13; private static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14; @@ -2067,23 +2068,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return mService.mAmInternal.isCurrentProfile(userId); } - /** - * Returns whether a stopping activity is present that should be stopped after visible, rather - * than idle. - * @return {@code true} if such activity is present. {@code false} otherwise. - */ - boolean isStoppingNoHistoryActivity() { - // Activities that are marked as nohistory should be stopped immediately after the resumed - // activity has become visible. - for (ActivityRecord record : mStoppingActivities) { - if (record.isNoHistory()) { - return true; - } - } - - return false; - } - /** * Processes the activities to be stopped or destroyed. This should be called when the resumed * activities are idle or drawn. @@ -2403,6 +2387,12 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } + void scheduleProcessStoppingAndFinishingActivities() { + if (!mHandler.hasMessages(PROCESS_STOPPING_AND_FINISHING_MSG)) { + mHandler.sendEmptyMessage(PROCESS_STOPPING_AND_FINISHING_MSG); + } + } + void removeSleepTimeouts() { mHandler.removeMessages(SLEEP_TIMEOUT_MSG); } @@ -2701,6 +2691,10 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mLaunchingActivityWakeLock.release(); } } break; + case PROCESS_STOPPING_AND_FINISHING_MSG: { + processStoppingAndFinishingActivities(null /* launchedActivity */, + false /* processPausingActivities */, "transit"); + } break; case LAUNCH_TASK_BEHIND_COMPLETE: { final ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); if (r != null) {