Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd63da50 authored by Louis Chang's avatar Louis Chang
Browse files

Reuse and reparent one-level root task to another display

A root task was reparented to a newly create root task
on another display while starting an existing activity
onto the display.

Since the original root task is now a child task after
reparented, the task surface size was not updated. So,
part of the surface was cropped and shown black.

Also fix a case where empty display (without any tasks)
was not awaken when stacks were reparented to it.

Bug: 150418176
Test: atest RootActivityContainerTests
Change-Id: I7eba20a973b5fd0fd050fedd06d3d700cb640f62
parent 962946c9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4429,6 +4429,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            position = findPositionForStack(position, stack, true /* adding */);

            super.addChild(stack, position);
            mAtmService.updateSleepIfNeededLocked();

            // The reparenting case is handled in WindowContainer.
            if (!stack.mReparenting) {
@@ -4440,6 +4441,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        protected void removeChild(ActivityStack stack) {
            super.removeChild(stack);
            mDisplayContent.onStackRemoved(stack);
            mAtmService.updateSleepIfNeededLocked();
            removeStackReferenceIfNeeded(stack);
        }

@@ -5653,7 +5655,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    void addStack(ActivityStack stack, int position) {
        setStackOnDisplay(stack, position);
        positionStackAt(stack, position);
        mAtmService.updateSleepIfNeededLocked();
    }

    void onStackRemoved(ActivityStack stack) {
@@ -5664,7 +5665,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            mPreferredTopFocusableStack = null;
        }
        releaseSelfIfNeeded();
        mAtmService.updateSleepIfNeededLocked();
        onStackOrderChanged(stack);
    }

+9 −1
Original line number Diff line number Diff line
@@ -2847,7 +2847,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
     * @param candidateTask The possible task the activity might be put in.
     * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
     */
    private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
    @VisibleForTesting
    ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
            @Nullable Task candidateTask, @Nullable ActivityOptions options,
            @Nullable LaunchParamsController.LaunchParams launchParams) {
        final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
@@ -2868,6 +2869,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            if (attachedDisplayId == INVALID_DISPLAY || attachedDisplayId == displayId) {
                return candidateTask.getStack();
            }
            // Or the candidate task is already a root task that can be reused by reparenting
            // it to the target display.
            if (candidateTask.isRootTask()) {
                final ActivityStack stack = candidateTask.getStack();
                displayContent.moveStackToDisplay(stack, true /* onTop */);
                return stack;
            }
        }

        int windowingMode;
+16 −0
Original line number Diff line number Diff line
@@ -787,6 +787,22 @@ public class RootActivityContainerTests extends ActivityTestsBase {
                secondaryDisplay.mDisplayId, result.getDisplayId());
    }

    @Test
    public void testGetValidLaunchStackOnDisplayWithCandidateRootTask() {
        // Create a root task with an activity on secondary display.
        final TestDisplayContent secondaryDisplay = new TestDisplayContent.Builder(mService, 300,
                600).build();
        final Task task = new ActivityTestsBase.StackBuilder(mRootWindowContainer).setDisplay(
                secondaryDisplay).build();
        final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(mService)
                .setTask(task).build();

        // Make sure the root task is valid and can be reused on default display.
        final ActivityStack stack = mRootWindowContainer.getValidLaunchStackOnDisplay(
                DEFAULT_DISPLAY, activity, task, null, null);
        assertEquals(task, stack);
    }

    @Test
    public void testSwitchUser_missingHomeRootTask() {
        doReturn(mFullscreenStack).when(mRootWindowContainer).getTopDisplayFocusedStack();