From cfe46219cfa5b75e5d444a7b2eedabda78c8b2e0 Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Tue, 30 Jul 2019 10:34:18 +0800 Subject: [PATCH] Resuming the restarting activities only if they were on stack top While starting multiple activities via Activity.startActivities(), more than one activities were launched within the same task. If the top activity is not fullscreen, the activities below were visible and stayed in RESUMED states. Only resume the top-most activity while restarting it. Bug: 136126538 Test: atest ActivityStackTests Change-Id: I63d69609d9ebc31899c22b9d913a587348725826 --- .../com/android/server/wm/ActivityRecord.java | 3 +-- .../com/android/server/wm/ActivityStack.java | 18 ++++-------------- .../android/server/wm/ActivityStackTests.java | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index fc36e9984c1bc..7d398a4a1c18f 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2918,7 +2918,7 @@ final class ActivityRecord extends ConfigurationContainer { return false; } - boolean handleAlreadyVisible() { + void handleAlreadyVisible() { stopFreezingScreenLocked(false); try { if (returningOptions != null) { @@ -2926,7 +2926,6 @@ final class ActivityRecord extends ConfigurationContainer { } } catch(RemoteException e) { } - return mState == RESUMED; } static void activityResumedLocked(IBinder token) { diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 8bdedffa581a4..699580b2633d4 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2088,7 +2088,7 @@ class ActivityStack extends ConfigurationContainer { boolean aboveTop = top != null; final boolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; - boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; + final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList activities = task.mActivities; @@ -2122,15 +2122,8 @@ class ActivityStack extends ConfigurationContainer { } if (!r.attachedToProcess()) { - if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, - resumeNextActivity, r)) { - if (activityNdx >= activities.size()) { - // Record may be removed if its process needs to restart. - activityNdx = activities.size() - 1; - } else { - resumeNextActivity = false; - } - } + makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, + resumeTopActivity && isTop, r); } else if (r.visible) { // If this activity is already visible, then there is nothing to do here. if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, @@ -2140,10 +2133,7 @@ class ActivityStack extends ConfigurationContainer { r.makeClientVisible(); } - if (r.handleAlreadyVisible()) { - resumeNextActivity = false; - } - + r.handleAlreadyVisible(); if (notifyClients) { r.makeActiveIfNeeded(starting); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 60c5f0bd7188d..c83e5cb71febd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -1122,6 +1123,22 @@ public class ActivityStackTests extends ActivityTestsBase { assertThat(result).isEqualTo(taskTop); } + @Test + public void testNonTopVisibleActivityNotResume() { + final ActivityRecord nonTopVisibleActivity = + new ActivityBuilder(mService).setTask(mTask).build(); + new ActivityBuilder(mService).setTask(mTask).build(); + doReturn(false).when(nonTopVisibleActivity).attachedToProcess(); + doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleIgnoringKeyguard(anyBoolean()); + doNothing().when(mSupervisor).startSpecificActivityLocked(any(), anyBoolean(), + anyBoolean()); + + mStack.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */); + verify(mSupervisor).startSpecificActivityLocked(any(), eq(false) /* andResume */, + anyBoolean()); + } + private void verifyShouldSleepActivities(boolean focusedStack, boolean keyguardGoingAway, boolean displaySleeping, boolean expected) { final ActivityDisplay display = mock(ActivityDisplay.class);