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
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1b0bec5..e002e62 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2604,11 +2604,6 @@
                 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 @@
                                 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 @@
                     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");
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index cde866b..e8045e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -33,7 +33,6 @@
 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.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 @@
         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 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 @@
         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.
      */
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 0d31d38..56c8bd1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1045,6 +1045,9 @@
             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());