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

Commit 8d5de97b authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Fix result code of launching existing activity in split

Since all secondary leaf tasks will be reparented to the organizer
created task, when launching an existing task in background in
split-screen mode, the root task mTargetStack is always the
organizer created task which is always the top of display area.
Then mMovedToFront is always set to false.

This may cause missing some launch metrics in split-screen because
ActivityMetricsLogger won't count the number for result code
START_DELIVERED_TO_TOP.

The test testSplitScreenTaskToFront didn't catch the problem
because it still creates tasks in the old way (multiple split
secondary root tasks under display area) which doesn't exist
in current design.

Fixes: 176277089
Test: ActivityStarterTests#testSplitScreenDeliverToTop
      ActivityStarterTests#testSplitScreenTaskToFront

Change-Id: I6bdb1faf8f7dbfb1e8a6f75279b87ffc9072fb31
parent a0334be8
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -2604,11 +2604,6 @@ class ActivityStarter {
                final Task launchStack = getLaunchStack(mStartActivity, mLaunchFlags, intentTask,
                        mOptions);
                if (launchStack == null || launchStack == mTargetStack) {
                    // Do not set mMovedToFront to true below for split-screen-top stack, or
                    // START_TASK_TO_FRONT will be returned and trigger unexpected animations when a
                    // new intent has delivered.
                    final boolean isSplitScreenTopStack = mTargetStack.isTopSplitScreenStack();

                    // TODO(b/151572268): Figure out a better way to move tasks in above 2-levels
                    //  tasks hierarchies.
                    if (mTargetStack != intentTask
@@ -2617,6 +2612,11 @@ class ActivityStarter {
                                false /* includingParents */);
                        intentTask = intentTask.getParent().asTask();
                    }
                    // If the task is in multi-windowing mode, the activity may already be on
                    // the top (visible to user but not the global top), then the result code
                    // should be START_DELIVERED_TO_TOP instead of START_TASK_TO_FRONT.
                    final boolean wasTopOfVisibleRootTask = intentActivity.mVisibleRequested
                            && intentActivity == mTargetStack.topRunningActivity();
                    // We only want to move to the front, if we aren't going to launch on a
                    // different stack. If we launch on a different stack, we will put the
                    // task on top there.
@@ -2625,7 +2625,7 @@ class ActivityStarter {
                    mTargetStack.moveTaskToFront(intentTask, mNoAnimation, mOptions,
                            mStartActivity.appTimeTracker, DEFER_RESUME,
                            "bringingFoundTaskToFront");
                    mMovedToFront = !isSplitScreenTopStack;
                    mMovedToFront = !wasTopOfVisibleRootTask;
                } else {
                    intentTask.reparent(launchStack, ON_TOP, REPARENT_MOVE_ROOT_TASK_TO_FRONT,
                            ANIMATE, DEFER_RESUME, "reparentToTargetStack");
+29 −26
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
@@ -84,6 +83,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.service.voice.IVoiceInteractionSession;
import android.util.Pair;
import android.view.Gravity;

import androidx.test.filters.SmallTest;
@@ -434,17 +434,12 @@ public class ActivityStarterTests extends WindowTestsBase {
        final ActivityStarter starter = prepareStarter(
                FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP,
                false /* mockGetLaunchStack */);
        final ActivityRecord splitPrimaryFocusActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord splitSecondReusableActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        splitPrimaryFocusActivity.getRootTask()
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        splitSecondReusableActivity.getRootTask()
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        final Pair<ActivityRecord, ActivityRecord> activities = createActivitiesInSplit();
        final ActivityRecord splitPrimaryFocusActivity = activities.first;
        final ActivityRecord splitSecondReusableActivity = activities.second;

        // Set focus back to primary.
        splitPrimaryFocusActivity.getRootTask().moveToFront("testSplitScreenDeliverToTop");
        splitPrimaryFocusActivity.moveFocusableActivityToTop("testSplitScreenDeliverToTop");

        // Start activity and delivered new intent.
        starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent);
@@ -463,24 +458,15 @@ public class ActivityStarterTests extends WindowTestsBase {
    public void testSplitScreenTaskToFront() {
        final ActivityStarter starter = prepareStarter(
                FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP, false);
        final ActivityRecord splitSecondReusableActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord splitSecondTopActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord splitPrimaryFocusActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        splitPrimaryFocusActivity.getRootTask()
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        splitSecondReusableActivity.getRootTask()
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        splitSecondTopActivity.getRootTask()
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);

        // Make it on top of split-screen-secondary.
        splitSecondTopActivity.getRootTask().moveToFront("testSplitScreenTaskToFront");
        final Pair<ActivityRecord, ActivityRecord> activities = createActivitiesInSplit();
        final ActivityRecord splitPrimaryFocusActivity = activities.first;
        final ActivityRecord splitSecondReusableActivity = activities.second;
        final ActivityRecord splitSecondTopActivity = new ActivityBuilder(mAtm).setCreateTask(true)
                .setParentTask(splitSecondReusableActivity.getRootTask()).build();
        assertTrue(splitSecondTopActivity.inSplitScreenSecondaryWindowingMode());

        // Let primary stack has focus.
        splitPrimaryFocusActivity.getRootTask().moveToFront("testSplitScreenTaskToFront");
        splitPrimaryFocusActivity.moveFocusableActivityToTop("testSplitScreenTaskToFront");

        // Start activity and delivered new intent.
        starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent);
@@ -491,6 +477,23 @@ public class ActivityStarterTests extends WindowTestsBase {
        assertEquals(START_TASK_TO_FRONT, result);
    }

    /** Returns 2 activities. The first is in primary and the second is in secondary. */
    private Pair<ActivityRecord, ActivityRecord> createActivitiesInSplit() {
        final TestSplitOrganizer splitOrg = new TestSplitOrganizer(mAtm);
        // The fullscreen windowing mode activity will be moved to split-secondary by
        // TestSplitOrganizer when a split-primary task appears.
        final ActivityRecord splitSecondActivity =
                new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord splitPrimaryActivity = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).setCreateActivity(true)
                .build().getTopMostActivity();
        splitPrimaryActivity.mVisibleRequested = splitSecondActivity.mVisibleRequested = true;

        assertEquals(splitOrg.mPrimary, splitPrimaryActivity.getRootTask());
        assertEquals(splitOrg.mSecondary, splitSecondActivity.getRootTask());
        return Pair.create(splitPrimaryActivity, splitSecondActivity);
    }

    /**
     * Tests activity is cleaned up properly in a task mode violation.
     */
+3 −0
Original line number Diff line number Diff line
@@ -1045,6 +1045,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
            spyOn(task);
            task.mUserId = mUserId;
            Task rootTask = task.getRootTask();
            if (task != rootTask && !Mockito.mockingDetails(rootTask).isSpy()) {
                spyOn(rootTask);
            }
            doNothing().when(rootTask).startActivityLocked(
                    any(), any(), anyBoolean(), anyBoolean(), any());