From b5d8f8b185c69f9d02835a75bbae2ecf9363a227 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Wed, 23 Oct 2019 13:01:40 +0800 Subject: [PATCH] Check that should resume activity directly while relaunch. When running ActivityLifecycleSplitScreenTests test testResumedWhenRecreatedFromInNonFocusedStack, we found that an activity could have an extra paused lifecycle before resumed, this is because one of the activity state in this stack is pausing, so the activity behind it be relaunch to pause state. To prevent another extra lifecycle, we can check that will the activity goes to resume directly while relaunch. Bug: 127741025 Test: run tests in android.server.am.lifecycle Change-Id: I7f0520ec57250f0161741704d0f6ae79ced0139d --- .../com/android/server/wm/ActivityRecord.java | 43 ++++++++++--------- .../com/android/server/wm/ActivityStack.java | 3 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b9cd766cef798..d7c1473104363 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4620,16 +4620,25 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** - * Check if activity should be moved to RESUMED state. The activity: - * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)}) - * - should be focusable + * Check if activity should be moved to RESUMED state. + * See {@link #shouldBeResumed(ActivityRecord)} * @param activeActivity the activity that is active or just completed pause action. We won't * resume if this activity is active. */ @VisibleForTesting boolean shouldResumeActivity(ActivityRecord activeActivity) { - return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED) - && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE; + return shouldBeResumed(activeActivity) && !isState(RESUMED); + } + + /** + * Check if activity should be RESUMED now. The activity: + * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)}) + * - should be focusable + */ + private boolean shouldBeResumed(ActivityRecord activeActivity) { + return shouldMakeActive(activeActivity) && isFocusable() + && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE + && canResumeByCompat(); } /** @@ -6905,23 +6914,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A deferRelaunchUntilPaused = true; preserveWindowOnDeferredRelaunch = preserveWindow; return true; - } else if (mState == RESUMED) { - // Try to optimize this case: the configuration is changing and we need to restart - // the top, resumed activity. Instead of doing the normal handshaking, just say - // "restart!". - if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, - "Config is relaunching resumed " + this); - - if (DEBUG_STATES && !visible) { - Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this - + " called by " + Debug.getCallers(4)); - } - - relaunchActivityLocked(true /* andResume */, preserveWindow); } else { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, - "Config is relaunching non-resumed " + this); - relaunchActivityLocked(false /* andResume */, preserveWindow); + "Config is relaunching " + this); + if (DEBUG_STATES && !visible) { + Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this + + " called by " + Debug.getCallers(4)); + } + relaunchActivityLocked(preserveWindow); } // All done... tell the caller we weren't able to keep this activity around. @@ -7019,12 +7019,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A | CONFIG_SCREEN_LAYOUT)) != 0; } - void relaunchActivityLocked(boolean andResume, boolean preserveWindow) { + void relaunchActivityLocked(boolean preserveWindow) { if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) { configChangeFlags = 0; return; } + final boolean andResume = shouldBeResumed(null /*activeActivity*/); List pendingResults = null; List pendingNewIntents = null; if (andResume) { diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 8e3995bfd8724..edf8789b3688d 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -1792,8 +1792,7 @@ class ActivityStack extends ConfigurationContainer { if (prev.deferRelaunchUntilPaused) { // Complete the deferred relaunch that was waiting for pause to complete. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev); - prev.relaunchActivityLocked(false /* andResume */, - prev.preserveWindowOnDeferredRelaunch); + prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch); } else if (wasStopping) { // We are also stopping, the stop request must have gone soon after the pause. // We can't clobber it, because the stop confirmation will not be handled.