diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index df046634da48e..c2025368baa71 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2607,11 +2607,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 @@ -2620,6 +2615,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. @@ -2628,7 +2628,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"); 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 cde866b19df83..e8045e06d9fff 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.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 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 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 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 0d31d3874785b..56c8bd12ac067 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 @@ 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());