Loading services/core/java/com/android/server/wm/ActivityRecord.java +26 −12 Original line number Diff line number Diff line Loading @@ -2761,19 +2761,33 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // than destroy immediately. final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.mVisibleRequested); if (isCurrentVisible && isNextNotYetVisible) { // Clear last paused activity to ensure top activity can be resumed during sleeping. if (isNextNotYetVisible && mDisplayContent.isSleeping() && next == next.getRootTask().mLastPausedActivity) { next.getRootTask().mLastPausedActivity = null; } if (isCurrentVisible) { if (isNextNotYetVisible) { // Add this activity to the list of stopping activities. It will be processed and // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); setState(STOPPING, "completeFinishing"); } else if (addToFinishingAndWaitForIdle()) { // We added this activity to the finishing list and something else is becoming resumed. // The activity will complete finishing when the next activity reports idle. No need to // do anything else here. // We added this activity to the finishing list and something else is becoming // resumed. The activity will complete finishing when the next activity reports // idle. No need to do anything else here. } else { // Not waiting for the next one to become visible, and nothing else will be resumed in // place of this activity - requesting destruction right away. // Not waiting for the next one to become visible, and nothing else will be // resumed in place of this activity - requesting destruction right away. activityRemoved = destroyIfPossible(reason); } } else { // Just need to make sure the next activities can be resumed (if needed) and is free // to destroy this activity since it is currently not visible. addToFinishingAndWaitForIdle(); activityRemoved = destroyIfPossible(reason); } Loading services/core/java/com/android/server/wm/RootWindowContainer.java +1 −0 Original line number Diff line number Diff line Loading @@ -2379,6 +2379,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } return resumed; }, false /* initValue */); result |= resumedOnDisplay; if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume Loading services/core/java/com/android/server/wm/TaskDisplayArea.java +6 −0 Original line number Diff line number Diff line Loading @@ -1189,6 +1189,12 @@ final class TaskDisplayArea extends DisplayArea<Task> { return; } // Clear last paused activity if focused root task changed while sleeping, so that the // top activity of current focused task can be resumed. if (mDisplayContent.isSleeping()) { currentFocusedTask.mLastPausedActivity = null; } mLastFocusedStack = prevFocusedTask; EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, mDisplayContent.mDisplayId, Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +31 −4 Original line number Diff line number Diff line Loading @@ -1019,6 +1019,32 @@ public class ActivityRecordTests extends WindowTestsBase { verify(topActivity, never()).destroyIfPossible(anyString()); } /** * Verify that complete finish request for top invisible activity must not be delayed while * sleeping, but next invisible activity must be resumed (and paused/stopped) */ @Test public void testCompleteFinishing_noWaitForNextVisible_sleeping() { // Create a top activity on a new task final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); mDisplayContent.setIsSleeping(true); doReturn(true).when(mActivity).shouldBeVisible(); topActivity.mVisibleRequested = false; topActivity.nowVisible = false; topActivity.finishing = true; topActivity.setState(STOPPED, "true"); // Mark the activity behind (on a separate task) as not visible mActivity.mVisibleRequested = false; mActivity.nowVisible = false; mActivity.setState(STOPPED, "test"); clearInvocations(mActivity); topActivity.completeFinishing("test"); verify(mActivity).setState(eq(RESUMED), any()); verify(topActivity).destroyIfPossible(anyString()); } /** * Verify that complete finish request for invisible activity must not be delayed. */ Loading Loading @@ -1232,12 +1258,13 @@ public class ActivityRecordTests extends WindowTestsBase { */ @Test public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() { // Empty the home stack. final Task homeStack = mActivity.getDisplayArea().getRootHomeTask(); homeStack.forAllLeafTasks((t) -> { homeStack.removeChild(t, "test"); // Empty the home root task. final Task homeRootTask = mActivity.getDisplayArea().getRootHomeTask(); homeRootTask.forAllLeafTasks((t) -> { homeRootTask.removeChild(t, "test"); }, true /* traverseTopToBottom */); mActivity.finishing = true; mActivity.mVisibleRequested = true; spyOn(mStack); // Try to finish the last activity above the home stack. Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +26 −12 Original line number Diff line number Diff line Loading @@ -2761,19 +2761,33 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // than destroy immediately. final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.mVisibleRequested); if (isCurrentVisible && isNextNotYetVisible) { // Clear last paused activity to ensure top activity can be resumed during sleeping. if (isNextNotYetVisible && mDisplayContent.isSleeping() && next == next.getRootTask().mLastPausedActivity) { next.getRootTask().mLastPausedActivity = null; } if (isCurrentVisible) { if (isNextNotYetVisible) { // Add this activity to the list of stopping activities. It will be processed and // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); setState(STOPPING, "completeFinishing"); } else if (addToFinishingAndWaitForIdle()) { // We added this activity to the finishing list and something else is becoming resumed. // The activity will complete finishing when the next activity reports idle. No need to // do anything else here. // We added this activity to the finishing list and something else is becoming // resumed. The activity will complete finishing when the next activity reports // idle. No need to do anything else here. } else { // Not waiting for the next one to become visible, and nothing else will be resumed in // place of this activity - requesting destruction right away. // Not waiting for the next one to become visible, and nothing else will be // resumed in place of this activity - requesting destruction right away. activityRemoved = destroyIfPossible(reason); } } else { // Just need to make sure the next activities can be resumed (if needed) and is free // to destroy this activity since it is currently not visible. addToFinishingAndWaitForIdle(); activityRemoved = destroyIfPossible(reason); } Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +1 −0 Original line number Diff line number Diff line Loading @@ -2379,6 +2379,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } return resumed; }, false /* initValue */); result |= resumedOnDisplay; if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume Loading
services/core/java/com/android/server/wm/TaskDisplayArea.java +6 −0 Original line number Diff line number Diff line Loading @@ -1189,6 +1189,12 @@ final class TaskDisplayArea extends DisplayArea<Task> { return; } // Clear last paused activity if focused root task changed while sleeping, so that the // top activity of current focused task can be resumed. if (mDisplayContent.isSleeping()) { currentFocusedTask.mLastPausedActivity = null; } mLastFocusedStack = prevFocusedTask; EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, mDisplayContent.mDisplayId, Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +31 −4 Original line number Diff line number Diff line Loading @@ -1019,6 +1019,32 @@ public class ActivityRecordTests extends WindowTestsBase { verify(topActivity, never()).destroyIfPossible(anyString()); } /** * Verify that complete finish request for top invisible activity must not be delayed while * sleeping, but next invisible activity must be resumed (and paused/stopped) */ @Test public void testCompleteFinishing_noWaitForNextVisible_sleeping() { // Create a top activity on a new task final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); mDisplayContent.setIsSleeping(true); doReturn(true).when(mActivity).shouldBeVisible(); topActivity.mVisibleRequested = false; topActivity.nowVisible = false; topActivity.finishing = true; topActivity.setState(STOPPED, "true"); // Mark the activity behind (on a separate task) as not visible mActivity.mVisibleRequested = false; mActivity.nowVisible = false; mActivity.setState(STOPPED, "test"); clearInvocations(mActivity); topActivity.completeFinishing("test"); verify(mActivity).setState(eq(RESUMED), any()); verify(topActivity).destroyIfPossible(anyString()); } /** * Verify that complete finish request for invisible activity must not be delayed. */ Loading Loading @@ -1232,12 +1258,13 @@ public class ActivityRecordTests extends WindowTestsBase { */ @Test public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() { // Empty the home stack. final Task homeStack = mActivity.getDisplayArea().getRootHomeTask(); homeStack.forAllLeafTasks((t) -> { homeStack.removeChild(t, "test"); // Empty the home root task. final Task homeRootTask = mActivity.getDisplayArea().getRootHomeTask(); homeRootTask.forAllLeafTasks((t) -> { homeRootTask.removeChild(t, "test"); }, true /* traverseTopToBottom */); mActivity.finishing = true; mActivity.mVisibleRequested = true; spyOn(mStack); // Try to finish the last activity above the home stack. Loading