Use resolved windowing mode to match launch root

WM core offers WindowContainerTransaction#setLaunchRoot() API to
override launch root task for specific windowing modes and activity
types. However before this CL we only pass windowing mode in
ActivityOptions when selecting root task, which will make windowing mode
most of the time unspecified, which diminishes the use of the API.

This can help whoever needs to differentiate launch root for freeform
tasks and fullscreen tasks.

Bug: 182514695
Test: WCT#setLaunchRoot() takes effect with app launches with specific
windowing mode that is initiated by launcher.
Test: atest TaskDisplayAreaTests

Change-Id: I8113d3c9a82c8202f3881b5c08347fcb765861c6
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1212302..2a768e7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2818,7 +2818,7 @@
      * @param launchParams   The resolved launch params to use.
      * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
      * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
-     * @return The roott task to use for the launch or INVALID_TASK_ID.
+     * @return The root task to use for the launch or INVALID_TASK_ID.
      */
     Task getLaunchRootTask(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop,
@@ -2887,7 +2887,7 @@
                 // Falling back to default task container
                 taskDisplayArea = taskDisplayArea.mDisplayContent.getDefaultTaskDisplayArea();
                 rootTask = taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,
-                        activityType, onTop);
+                        launchParams, activityType, onTop);
                 if (rootTask != null) {
                     return rootTask;
                 }
@@ -2942,7 +2942,8 @@
             }
         }
 
-        return container.getOrCreateRootTask(r, options, candidateTask, activityType, onTop);
+        return container.getOrCreateRootTask(
+                r, options, candidateTask, launchParams, activityType, onTop);
     }
 
     /** @return true if activity record is null or can be launched on provided display. */
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ed92fd0..f0f4daf 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -57,6 +57,7 @@
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.util.function.pooled.PooledPredicate;
+import com.android.server.wm.LaunchParamsController.LaunchParams;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1080,11 +1081,17 @@
      * @see #getOrCreateRootTask(int, int, boolean)
      */
     Task getOrCreateRootTask(@Nullable ActivityRecord r,
-            @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
-            boolean onTop) {
-        // First preference is the windowing mode in the activity options if set.
-        int windowingMode = (options != null)
-                ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+            @Nullable ActivityOptions options, @Nullable Task candidateTask,
+            @Nullable LaunchParams launchParams, int activityType, boolean onTop) {
+        int windowingMode = WINDOWING_MODE_UNDEFINED;
+        if (launchParams != null) {
+            // If launchParams isn't null, windowing mode is already resolved.
+            windowingMode = launchParams.mWindowingMode;
+        } else if (options != null) {
+            // If launchParams is null and options isn't let's use the windowing mode in the
+            // options.
+            windowingMode = options.getLaunchWindowingMode();
+        }
         // Validate that our desired windowingMode will work under the current conditions.
         // UNDEFINED windowing mode is a valid result and means that the new root task will inherit
         // it's display's windowing mode.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index e22cda6..eba5634 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -42,16 +42,20 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.app.ActivityOptions;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.wm.LaunchParamsController.LaunchParams;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -87,6 +91,48 @@
     }
 
     @Test
+    public void getOrCreateLaunchRootRespectsResolvedWindowingMode() {
+        final Task rootTask = createTaskStackOnDisplay(
+                WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        rootTask.mCreatedByOrganizer = true;
+        final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
+        taskDisplayArea.setLaunchRootTask(
+                rootTask, new int[]{WINDOWING_MODE_FREEFORM}, new int[]{ACTIVITY_TYPE_STANDARD});
+
+        final Task candidateRootTask = createTaskStackOnDisplay(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
+        final LaunchParams launchParams = new LaunchParams();
+        launchParams.mWindowingMode = WINDOWING_MODE_FREEFORM;
+
+        final Task actualRootTask = taskDisplayArea.getOrCreateRootTask(
+                activity, null /* options */, candidateRootTask,
+                launchParams, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        assertSame(rootTask, actualRootTask.getRootTask());
+    }
+
+    @Test
+    public void getOrCreateLaunchRootUsesActivityOptionsWindowingMode() {
+        final Task rootTask = createTaskStackOnDisplay(
+                WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        rootTask.mCreatedByOrganizer = true;
+        final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
+        taskDisplayArea.setLaunchRootTask(
+                rootTask, new int[]{WINDOWING_MODE_FREEFORM}, new int[]{ACTIVITY_TYPE_STANDARD});
+
+        final Task candidateRootTask = createTaskStackOnDisplay(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
+        final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+
+        final Task actualRootTask = taskDisplayArea.getOrCreateRootTask(
+                activity, options, candidateRootTask,
+                null /* launchParams */, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        assertSame(rootTask, actualRootTask.getRootTask());
+    }
+
+    @Test
     public void testActivityWithZBoost_taskDisplayAreaDoesNotMoveUp() {
         final Task stack = createTaskStackOnDisplay(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);