Merge changes I777cd7e3,I6d6dea8e,I7c9095ce into main

* changes:
  Handle RootTaskInfo with no child tasks
  Disable WorkProfilePolicy for multiwindow droidfood
  Test coverage for Work and Private profile policies
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt
index d62ab85..1945c25 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/PrivateProfilePolicy.kt
@@ -39,11 +39,11 @@
     override suspend fun check(content: DisplayContentModel): PolicyResult {
         // The systemUI notification shade isn't a private profile app, skip.
         if (content.systemUiState.shadeExpanded) {
-            return NotMatched(policy = NAME, reason = "Notification shade is expanded")
+            return NotMatched(policy = NAME, reason = SHADE_EXPANDED)
         }
 
         // Find the first visible rootTaskInfo with a child task owned by a private user
-        val (rootTask, childTask) =
+        val childTask =
             content.rootTasks
                 .filter { it.isVisible }
                 .firstNotNullOfOrNull { root ->
@@ -52,22 +52,24 @@
                         .firstOrNull {
                             profileTypes.getProfileType(it.userId) == ProfileType.PRIVATE
                         }
-                        ?.let { root to it }
                 }
-                ?: return NotMatched(policy = NAME, reason = "No private profile tasks are visible")
+                ?: return NotMatched(policy = NAME, reason = NO_VISIBLE_TASKS)
 
         // If matched, return parameters needed to modify the request.
         return Matched(
             policy = NAME,
-            reason = "At least one private profile task is visible",
+            reason = PRIVATE_TASK_VISIBLE,
             CaptureParameters(
                 type = FullScreen(content.displayId),
-                component = childTask.componentName ?: rootTask.topActivity,
+                component = content.rootTasks.first { it.isVisible }.topActivity,
                 owner = UserHandle.of(childTask.userId),
             )
         )
     }
     companion object {
         const val NAME = "PrivateProfile"
+        const val SHADE_EXPANDED = "Notification shade is expanded"
+        const val NO_VISIBLE_TASKS = "No private profile tasks are visible"
+        const val PRIVATE_TASK_VISIBLE = "At least one private profile task is visible"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt
index 3789371..f768cfb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/RootTaskInfoExt.kt
@@ -30,3 +30,5 @@
         )
     }
 }
+
+internal fun RootTaskInfo.hasChildTasks() = childTaskUserIds.isNotEmpty()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt
index b781ae9..fdf16aa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/WorkProfilePolicy.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenshot.policy
 
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.app.WindowConfiguration.WINDOWING_MODE_PINNED
 import android.os.UserHandle
 import com.android.systemui.screenshot.data.model.DisplayContentModel
@@ -24,6 +25,7 @@
 import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
 import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
 import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask
+import com.android.window.flags.Flags
 import javax.inject.Inject
 import kotlinx.coroutines.flow.first
 
@@ -41,26 +43,36 @@
     override suspend fun check(content: DisplayContentModel): PolicyResult {
         // The systemUI notification shade isn't a work app, skip.
         if (content.systemUiState.shadeExpanded) {
-            return NotMatched(policy = NAME, reason = "Notification shade is expanded")
+            return NotMatched(policy = NAME, reason = SHADE_EXPANDED)
+        }
+
+        if (Flags.enableDesktopWindowingMode()) {
+            content.rootTasks.firstOrNull()?.also {
+                if (it.windowingMode == WINDOWING_MODE_FREEFORM) {
+                    return NotMatched(policy = NAME, reason = DESKTOP_MODE_ENABLED)
+                }
+            }
         }
 
         // Find the first non PiP rootTask with a top child task owned by a work user
         val (rootTask, childTask) =
             content.rootTasks
-                .filter { it.isVisible && it.windowingMode != WINDOWING_MODE_PINNED }
+                .filter {
+                    it.isVisible && it.windowingMode != WINDOWING_MODE_PINNED && it.hasChildTasks()
+                }
                 .map { it to it.childTasksTopDown().first() }
                 .firstOrNull { (_, child) ->
                     profileTypes.getProfileType(child.userId) == ProfileType.WORK
                 }
                 ?: return NotMatched(
                     policy = NAME,
-                    reason = "The top-most non-PINNED task does not belong to a work profile user"
+                    reason = WORK_TASK_NOT_TOP,
                 )
 
         // If matched, return parameters needed to modify the request.
         return PolicyResult.Matched(
             policy = NAME,
-            reason = "The top-most non-PINNED task ($childTask) belongs to a work profile user",
+            reason = WORK_TASK_IS_TOP,
             CaptureParameters(
                 type = IsolatedTask(taskId = childTask.id, taskBounds = childTask.bounds),
                 component = childTask.componentName ?: rootTask.topActivity,
@@ -70,6 +82,13 @@
     }
 
     companion object {
-        val NAME = "WorkProfile"
+        const val NAME = "WorkProfile"
+        const val SHADE_EXPANDED = "Notification shade is expanded"
+        const val WORK_TASK_NOT_TOP =
+            "The top-most non-PINNED task does not belong to a work profile user"
+        const val WORK_TASK_IS_TOP = "The top-most non-PINNED task belongs to a work profile user"
+        const val DESKTOP_MODE_ENABLED =
+            "enable_desktop_windowing_mode is enabled and top " +
+                "RootTask has WINDOWING_MODE_FREEFORM"
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
index 621b058..254f1e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/data/model/DisplayContentScenarios.kt
@@ -188,6 +188,18 @@
      * actual values returned by ActivityTaskManager
      */
     object RootTasks {
+        /** An empty RootTaskInfo with no child tasks. */
+        val emptyWithNoChildTasks =
+            newRootTaskInfo(
+                taskId = 2,
+                visible = true,
+                running = true,
+                numActivities = 0,
+                bounds = FULL_SCREEN,
+            ) {
+                emptyList()
+            }
+
         /**
          * The empty RootTaskInfo that is always at the end of a list from ActivityTaskManager when
          * no other visible activities are in split mode
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
new file mode 100644
index 0000000..9e3ae05
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/PrivateProfilePolicyTest.kt
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.content.ComponentName
+import android.os.UserHandle
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.FILES
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE_PIP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.emptyRootSplit
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.fullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks.launcher
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.TaskSpec
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.pictureInPictureApp
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.singleFullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.splitScreenApps
+import com.android.systemui.screenshot.data.model.SystemUiState
+import com.android.systemui.screenshot.data.repository.profileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.FullScreen
+import com.android.systemui.screenshot.policy.TestUserIds.PERSONAL
+import com.android.systemui.screenshot.policy.TestUserIds.PRIVATE
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class PrivateProfilePolicyTest {
+    private val kosmos = Kosmos()
+    private val policy = PrivateProfilePolicy(kosmos.profileTypeRepository)
+
+    // TODO:
+    // private app in PIP
+    // private app below personal PIP app
+    // Freeform windows
+
+    @Test
+    fun shadeExpanded_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(
+                    spec = TaskSpec(taskId = 1002, name = YOUTUBE, userId = PRIVATE),
+                    shadeExpanded = true
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(NotMatched(PrivateProfilePolicy.NAME, PrivateProfilePolicy.SHADE_EXPANDED))
+    }
+
+    @Test
+    fun noPrivate_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL))
+            )
+
+        assertThat(result)
+            .isEqualTo(NotMatched(PrivateProfilePolicy.NAME, PrivateProfilePolicy.NO_VISIBLE_TASKS))
+    }
+
+    @Test
+    fun withPrivateFullScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PRIVATE))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateNotVisible_notMatched() = runTest {
+        val result =
+            policy.check(
+                DisplayContentModel(
+                    displayId = 0,
+                    systemUiState = SystemUiState(shadeExpanded = false),
+                    rootTasks =
+                        listOf(
+                            fullScreen(
+                                TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                                visible = true
+                            ),
+                            fullScreen(
+                                TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                                visible = false
+                            ),
+                            launcher(visible = false),
+                            emptyRootSplit,
+                        )
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.NO_VISIBLE_TASKS,
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateFocusedInSplitScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateNotFocusedInSplitScreen_isMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = PERSONAL),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PRIVATE),
+                    focusedTaskId = 1002
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivatePictureInPictureApp_isMatched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(TaskSpec(taskId = 1002, name = YOUTUBE_PIP, userId = PRIVATE))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE_PIP),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withPrivateAppBelowPictureInPictureApp_isMatched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(
+                    pip = TaskSpec(taskId = 1002, name = YOUTUBE_PIP, userId = PERSONAL),
+                    fullScreen = TaskSpec(taskId = 1003, name = FILES, userId = PRIVATE),
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                Matched(
+                    PrivateProfilePolicy.NAME,
+                    PrivateProfilePolicy.PRIVATE_TASK_VISIBLE,
+                    CaptureParameters(
+                        type = FullScreen(displayId = 0),
+                        component = ComponentName.unflattenFromString(YOUTUBE_PIP),
+                        owner = UserHandle.of(PRIVATE)
+                    )
+                )
+            )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
new file mode 100644
index 0000000..5d35528
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/policy/WorkProfilePolicyTest.kt
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot.policy
+
+import android.content.ComponentName
+import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.screenshot.data.model.DisplayContentModel
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.FILES
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.ActivityNames.YOUTUBE
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FREE_FORM
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.FULL_SCREEN
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.Bounds.SPLIT_TOP
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.RootTasks
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.TaskSpec
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.freeFormApps
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.pictureInPictureApp
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.singleFullScreen
+import com.android.systemui.screenshot.data.model.DisplayContentScenarios.splitScreenApps
+import com.android.systemui.screenshot.data.model.SystemUiState
+import com.android.systemui.screenshot.data.repository.profileTypeRepository
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
+import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
+import com.android.systemui.screenshot.policy.CaptureType.IsolatedTask
+import com.android.systemui.screenshot.policy.TestUserIds.PERSONAL
+import com.android.systemui.screenshot.policy.TestUserIds.WORK
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.DESKTOP_MODE_ENABLED
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.SHADE_EXPANDED
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.WORK_TASK_IS_TOP
+import com.android.systemui.screenshot.policy.WorkProfilePolicy.Companion.WORK_TASK_NOT_TOP
+import com.android.window.flags.Flags
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Rule
+import org.junit.Test
+
+class WorkProfilePolicyTest {
+    @JvmField @Rule val setFlagsRule = SetFlagsRule()
+
+    private val kosmos = Kosmos()
+    private val policy = WorkProfilePolicy(kosmos.profileTypeRepository)
+
+    /**
+     * There is no guarantee that every RootTaskInfo contains a non-empty list of child tasks. Test
+     * the case where the RootTaskInfo would match but child tasks are empty.
+     */
+    @Test
+    fun withEmptyChildTasks_notMatched() = runTest {
+        val result =
+            policy.check(
+                DisplayContentModel(
+                    displayId = 0,
+                    systemUiState = SystemUiState(shadeExpanded = false),
+                    rootTasks = listOf(RootTasks.emptyWithNoChildTasks)
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun noWorkApp_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL))
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFullScreen_shadeExpanded_notMatched() = runTest {
+        val result =
+            policy.check(
+                singleFullScreen(
+                    TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    shadeExpanded = true
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    SHADE_EXPANDED,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFullScreen_matched() = runTest {
+        val result =
+            policy.check(singleFullScreen(TaskSpec(taskId = 1002, name = FILES, userId = WORK)))
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1002, taskBounds = FULL_SCREEN),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withWorkFocusedInSplitScreen_matched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PERSONAL),
+                    focusedTaskId = 1002
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1002, taskBounds = SPLIT_TOP),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    fun withWorkNotFocusedInSplitScreen_notMatched() = runTest {
+        val result =
+            policy.check(
+                splitScreenApps(
+                    top = TaskSpec(taskId = 1002, name = FILES, userId = WORK),
+                    bottom = TaskSpec(taskId = 1003, name = YOUTUBE, userId = PERSONAL),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    WORK_TASK_NOT_TOP,
+                )
+            )
+    }
+
+    @Test
+    fun withWorkBelowPersonalPictureInPicture_matched() = runTest {
+        val result =
+            policy.check(
+                pictureInPictureApp(
+                    pip = TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    fullScreen = TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1003, taskBounds = FULL_SCREEN),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    fun withWorkFocusedInFreeForm_matched() = runTest {
+        val result =
+            policy.check(
+                freeFormApps(
+                    TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                PolicyResult.Matched(
+                    policy = WorkProfilePolicy.NAME,
+                    reason = WORK_TASK_IS_TOP,
+                    CaptureParameters(
+                        type = IsolatedTask(taskId = 1003, taskBounds = FREE_FORM),
+                        component = ComponentName.unflattenFromString(FILES),
+                        owner = UserHandle.of(WORK),
+                    )
+                )
+            )
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    fun withWorkFocusedInFreeForm_desktopModeEnabled_notMatched() = runTest {
+        val result =
+            policy.check(
+                freeFormApps(
+                    TaskSpec(taskId = 1002, name = YOUTUBE, userId = PERSONAL),
+                    TaskSpec(taskId = 1003, name = FILES, userId = WORK),
+                    focusedTaskId = 1003
+                )
+            )
+
+        assertThat(result)
+            .isEqualTo(
+                NotMatched(
+                    WorkProfilePolicy.NAME,
+                    DESKTOP_MODE_ENABLED,
+                )
+            )
+    }
+}