Merge "Make DeskopTaskView use latest TTV" into main
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index 89e9b3d..453057c 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -36,15 +36,6 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <!--
-         TODO(b249371338): DesktopTaskView extends from TaskView. TaskView expects TaskThumbnailView
-         and IconView with these ids to be present. Need to refactor RecentsView to accept child
-         views that do not inherint from TaskView only or create a generic TaskView that have
-         N number of tasks.
-     -->
-    <include layout="@layout/task_thumbnail"
-        android:visibility="gone" />
-
     <ViewStub
         android:id="@+id/icon"
         android:inflatedId="@id/icon"
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index dbe2b19..20a081b 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -30,6 +30,7 @@
 import android.view.ViewOutlineProvider
 import androidx.annotation.ColorInt
 import com.android.launcher3.Utilities
+import com.android.launcher3.util.ViewPool
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
@@ -42,7 +43,7 @@
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.launch
 
-class TaskThumbnailView : View {
+class TaskThumbnailView : View, ViewPool.Reusable {
     // TODO(b/335649589): Ideally create and obtain this from DI. This ViewModel should be scoped
     //  to [TaskView], and also shared between [TaskView] and [TaskThumbnailView]
     //  This is using a lazy for now because the dependencies cannot be obtained without DI.
@@ -71,7 +72,7 @@
             return _measuredBounds
         }
 
-    private var cornerRadius: Float = TaskCornerRadius.get(context)
+    private var overviewCornerRadius: Float = TaskCornerRadius.get(context)
     private var fullscreenCornerRadius: Float = QuickStepContract.getWindowCornerRadius(context)
 
     constructor(context: Context?) : super(context)
@@ -100,7 +101,7 @@
                 invalidate()
             }
         }
-        MainScope().launch { viewModel.recentsFullscreenProgress.collect { invalidateOutline() } }
+        MainScope().launch { viewModel.cornerRadiusProgress.collect { invalidateOutline() } }
         MainScope().launch {
             viewModel.inheritedScale.collect { viewModelInheritedScale ->
                 inheritedScale = viewModelInheritedScale
@@ -117,6 +118,11 @@
             }
     }
 
+    override fun onRecycle() {
+        // Do nothing
+        uiState = Uninitialized
+    }
+
     override fun onDraw(canvas: Canvas) {
         when (val uiStateVal = uiState) {
             is Uninitialized -> drawBackgroundOnly(canvas, Color.BLACK)
@@ -138,7 +144,7 @@
     override fun onConfigurationChanged(newConfig: Configuration?) {
         super.onConfigurationChanged(newConfig)
 
-        cornerRadius = TaskCornerRadius.get(context)
+        overviewCornerRadius = TaskCornerRadius.get(context)
         fullscreenCornerRadius = QuickStepContract.getWindowCornerRadius(context)
         invalidateOutline()
     }
@@ -159,8 +165,8 @@
 
     private fun getCurrentCornerRadius() =
         Utilities.mapRange(
-            viewModel.recentsFullscreenProgress.value,
-            cornerRadius,
+            viewModel.cornerRadiusProgress.value,
+            overviewCornerRadius,
             fullscreenCornerRadius
         ) / inheritedScale
 
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
index fe21174..d8729a6 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModel.kt
@@ -31,6 +31,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
@@ -47,7 +48,13 @@
     private val task = MutableStateFlow<Flow<Task?>>(flowOf(null))
     private var boundTaskIsRunning = false
 
-    val recentsFullscreenProgress = recentsViewData.fullscreenProgress
+    /**
+     * Progress for changes in corner radius. progress: 0 = overview corner radius; 1 = fullscreen
+     * corner radius.
+     */
+    val cornerRadiusProgress =
+        if (taskViewData.isOutlineFormedByThumbnailView) recentsViewData.fullscreenProgress
+        else MutableStateFlow(1f).asStateFlow()
     val inheritedScale =
         combine(recentsViewData.scale, taskViewData.scale) { recentsScale, taskScale ->
             recentsScale * taskScale
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
index a8b5112..7a9ecf2 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskViewData.kt
@@ -16,9 +16,14 @@
 
 package com.android.quickstep.task.viewmodel
 
+import com.android.quickstep.views.TaskViewType
 import kotlinx.coroutines.flow.MutableStateFlow
 
-class TaskViewData {
+class TaskViewData(taskViewType: TaskViewType) {
     // This is typically a View concern but it is used to invalidate rendering in other Views
     val scale = MutableStateFlow(1f)
+
+    // TODO(b/331753115): This property should not be in TaskViewData once TaskView is MVVM.
+    /** Whether outline of TaskView is formed by outline thumbnail view(s). */
+    val isOutlineFormedByThumbnailView: Boolean = taskViewType != TaskViewType.DESKTOP
 }
diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.java b/quickstep/src/com/android/quickstep/util/DesktopTask.java
index 307b2fa..a727aa2 100644
--- a/quickstep/src/com/android/quickstep/util/DesktopTask.java
+++ b/quickstep/src/com/android/quickstep/util/DesktopTask.java
@@ -18,7 +18,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskViewType;
 import com.android.systemui.shared.recents.model.Task;
 
 import java.util.List;
@@ -34,7 +34,7 @@
     public final List<Task> tasks;
 
     public DesktopTask(@NonNull List<Task> tasks) {
-        super(tasks.get(0), null, null, TaskView.Type.DESKTOP);
+        super(tasks.get(0), null, null, TaskViewType.DESKTOP);
         this.tasks = tasks;
     }
 
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index e8b611c..fba08a9 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -20,7 +20,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
-import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskViewType;
 import com.android.systemui.shared.recents.model.Task;
 
 import java.util.Arrays;
@@ -39,19 +39,18 @@
     public final Task task2;
     @Nullable
     public final SplitBounds mSplitBounds;
-    @TaskView.Type
-    public final int taskViewType;
+    public final TaskViewType taskViewType;
 
     public GroupTask(@NonNull Task task) {
         this(task, null, null);
     }
 
     public GroupTask(@NonNull Task t1, @Nullable Task t2, @Nullable SplitBounds splitBounds) {
-        this(t1, t2, splitBounds, t2 != null ? TaskView.Type.GROUPED : TaskView.Type.SINGLE);
+        this(t1, t2, splitBounds, t2 != null ? TaskViewType.GROUPED : TaskViewType.SINGLE);
     }
 
     protected GroupTask(@NonNull Task t1, @Nullable Task t2, @Nullable SplitBounds splitBounds,
-            @TaskView.Type int taskViewType) {
+            TaskViewType taskViewType) {
         task1 = t1;
         task2 = t2;
         mSplitBounds = splitBounds;
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
index 55bbd50..4333c8b 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.kt
@@ -27,6 +27,7 @@
 import android.view.View
 import android.view.ViewGroup
 import androidx.core.view.updateLayoutParams
+import com.android.launcher3.Flags.enableRefactorTaskThumbnail
 import com.android.launcher3.R
 import com.android.launcher3.util.RunnableList
 import com.android.launcher3.util.SplitConfigurationOptions
@@ -35,12 +36,13 @@
 import com.android.launcher3.util.rects.set
 import com.android.quickstep.BaseContainerInterface
 import com.android.quickstep.TaskOverlayFactory
+import com.android.quickstep.task.thumbnail.TaskThumbnailView
 import com.android.quickstep.util.RecentsOrientedState
 import com.android.systemui.shared.recents.model.Task
 
 /** TaskView that contains all tasks that are part of the desktop. */
 class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
-    TaskView(context, attrs) {
+    TaskView(context, attrs, type = TaskViewType.DESKTOP) {
 
     private val snapshotDrawParams =
         object : FullscreenDrawParams(context) {
@@ -48,7 +50,7 @@
             override fun computeTaskCornerRadius(context: Context) =
                 computeWindowCornerRadius(context)
         }
-    private val taskThumbnailViewPool =
+    private val taskThumbnailViewDeprecatedPool =
         ViewPool<TaskThumbnailViewDeprecated>(
             context,
             this,
@@ -89,6 +91,66 @@
         childCountAtInflation = childCount
     }
 
+    /** Updates this desktop task to the gives task list defined in `tasks` */
+    fun bind(
+        tasks: List<Task>,
+        orientedState: RecentsOrientedState,
+        taskOverlayFactory: TaskOverlayFactory
+    ) {
+        if (DEBUG) {
+            val sb = StringBuilder()
+            sb.append("bind tasks=").append(tasks.size).append("\n")
+            tasks.forEach { sb.append(" key=${it.key}\n") }
+            Log.d(TAG, sb.toString())
+        }
+        cancelPendingLoadTasks()
+        taskContainers =
+            tasks.map { task ->
+                val snapshotView =
+                    if (enableRefactorTaskThumbnail()) {
+                            TaskThumbnailView(context)
+                        } else {
+                            taskThumbnailViewDeprecatedPool.view
+                        }
+                        .also { snapshotView ->
+                            addView(
+                                snapshotView,
+                                // Add snapshotView to the front after initial views e.g. icon and
+                                // background.
+                                childCountAtInflation,
+                                LayoutParams(
+                                    ViewGroup.LayoutParams.WRAP_CONTENT,
+                                    ViewGroup.LayoutParams.WRAP_CONTENT
+                                )
+                            )
+                        }
+                TaskContainer(
+                    this,
+                    task,
+                    snapshotView,
+                    iconView,
+                    TransformingTouchDelegate(iconView.asView()),
+                    SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
+                    digitalWellBeingToast = null,
+                    showWindowsView = null,
+                    taskOverlayFactory
+                )
+            }
+        taskContainers.forEach { it.bind() }
+        setOrientationState(orientedState)
+    }
+
+    override fun onRecycle() {
+        super.onRecycle()
+        visibility = VISIBLE
+        taskContainers.forEach {
+            if (!enableRefactorTaskThumbnail()) {
+                removeView(it.thumbnailViewDeprecated)
+                taskThumbnailViewDeprecatedPool.recycle(it.thumbnailViewDeprecated)
+            }
+        }
+    }
+
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
         val containerWidth = MeasureSpec.getSize(widthMeasureSpec)
@@ -151,77 +213,6 @@
         }
     }
 
-    override fun onRecycle() {
-        super.onRecycle()
-        visibility = VISIBLE
-    }
-
-    /** Updates this desktop task to the gives task list defined in `tasks` */
-    fun bind(
-        tasks: List<Task>,
-        orientedState: RecentsOrientedState,
-        taskOverlayFactory: TaskOverlayFactory
-    ) {
-        if (DEBUG) {
-            val sb = StringBuilder()
-            sb.append("bind tasks=").append(tasks.size).append("\n")
-            tasks.forEach { sb.append(" key=${it.key}\n") }
-            Log.d(TAG, sb.toString())
-        }
-        cancelPendingLoadTasks()
-
-        if (!isTaskContainersInitialized()) {
-            taskContainers = arrayListOf()
-        }
-        val taskContainers = taskContainers as ArrayList
-        taskContainers.ensureCapacity(tasks.size)
-        tasks.forEachIndexed { index, task ->
-            val thumbnailViewDeprecated: TaskThumbnailViewDeprecated
-            if (index >= taskContainers.size) {
-                thumbnailViewDeprecated = taskThumbnailViewPool.view
-                // Add thumbnailView from to position after the initial child views.
-                addView(
-                    thumbnailViewDeprecated,
-                    childCountAtInflation,
-                    LayoutParams(
-                        ViewGroup.LayoutParams.WRAP_CONTENT,
-                        ViewGroup.LayoutParams.WRAP_CONTENT
-                    )
-                )
-            } else {
-                thumbnailViewDeprecated = taskContainers[index].thumbnailViewDeprecated
-            }
-            val taskContainer =
-                TaskContainer(
-                    this,
-                    task,
-                    // TODO(b/338360089): Support new TTV for DesktopTaskView
-                    thumbnailView = null,
-                    thumbnailViewDeprecated,
-                    iconView,
-                    TransformingTouchDelegate(iconView.asView()),
-                    SplitConfigurationOptions.STAGE_POSITION_UNDEFINED,
-                    digitalWellBeingToast = null,
-                    showWindowsView = null,
-                    taskOverlayFactory
-                )
-            if (index >= taskContainers.size) {
-                taskContainers.add(taskContainer)
-            } else {
-                taskContainers[index] = taskContainer
-            }
-            taskContainer.bind()
-        }
-        repeat(taskContainers.size - tasks.size) {
-            with(taskContainers.removeLast()) {
-                removeView(thumbnailViewDeprecated)
-                taskThumbnailViewPool.recycle(thumbnailViewDeprecated)
-            }
-        }
-
-        setOrientationState(orientedState)
-    }
-
     override fun needsUpdate(dataChange: Int, flag: Int) =
         if (flag == FLAG_UPDATE_THUMBNAIL) super.needsUpdate(dataChange, flag) else false
 
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
index b070244..6523ba7 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
@@ -49,7 +49,7 @@
  * (Icon loading sold separately, fees may apply. Shipping & Handling for Overlays not included).
  */
 class GroupedTaskView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
-    TaskView(context, attrs) {
+    TaskView(context, attrs, type = TaskViewType.GROUPED) {
     // TODO(b/336612373): Support new TTV for GroupedTaskView
     var splitBoundsConfig: SplitConfigurationOptions.SplitBounds? = null
         private set
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 22f3c1d..7b6d383 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1824,7 +1824,7 @@
             // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
             // to be a temporary container for the remaining task.
             TaskView taskView = getTaskViewFromPool(
-                    isRemovalNeeded ? TaskView.Type.SINGLE : groupTask.taskViewType);
+                    isRemovalNeeded ? TaskViewType.SINGLE : groupTask.taskViewType);
             if (taskView instanceof GroupedTaskView) {
                 boolean firstTaskIsLeftTopTask =
                         groupTask.mSplitBounds.leftTopTaskId == groupTask.task1.key.id;
@@ -2600,16 +2600,16 @@
      * Handle the edge case where Recents could increment task count very high over long
      * period of device usage. Probably will never happen, but meh.
      */
-    private TaskView getTaskViewFromPool(@TaskView.Type int type) {
+    private TaskView getTaskViewFromPool(TaskViewType type) {
         TaskView taskView;
         switch (type) {
-            case TaskView.Type.GROUPED:
+            case GROUPED:
                 taskView = mGroupedTaskViewPool.getView();
                 break;
-            case TaskView.Type.DESKTOP:
+            case DESKTOP:
                 taskView = mDesktopTaskViewPool.getView();
                 break;
-            case TaskView.Type.SINGLE:
+            case SINGLE:
             default:
                 taskView = mTaskViewPool.getView();
         }
@@ -2840,12 +2840,12 @@
             // Add an empty view for now until the task plan is loaded and applied
             final TaskView taskView;
             if (needDesktopTask) {
-                taskView = getTaskViewFromPool(TaskView.Type.DESKTOP);
+                taskView = getTaskViewFromPool(TaskViewType.DESKTOP);
                 mTmpRunningTasks = Arrays.copyOf(runningTasks, runningTasks.length);
                 ((DesktopTaskView) taskView).bind(Arrays.asList(mTmpRunningTasks),
                         mOrientationState, mTaskOverlayFactory);
             } else if (needGroupTaskView) {
-                taskView = getTaskViewFromPool(TaskView.Type.GROUPED);
+                taskView = getTaskViewFromPool(TaskViewType.GROUPED);
                 mTmpRunningTasks = new Task[]{runningTasks[0], runningTasks[1]};
                 // When we create a placeholder task view mSplitBoundsConfig will be null, but with
                 // the actual app running we won't need to show the thumbnail until all the tasks
@@ -2853,7 +2853,7 @@
                 ((GroupedTaskView)taskView).bind(mTmpRunningTasks[0], mTmpRunningTasks[1],
                         mOrientationState, mTaskOverlayFactory, mSplitBoundsConfig);
             } else {
-                taskView = getTaskViewFromPool(TaskView.Type.SINGLE);
+                taskView = getTaskViewFromPool(TaskViewType.SINGLE);
                 // The temporary running task is only used for the duration between the start of the
                 // gesture and the task list is loaded and applied
                 mTmpRunningTasks = new Task[]{runningTasks[0]};
diff --git a/quickstep/src/com/android/quickstep/views/TaskContainer.kt b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
index 2e01e7e..0648986 100644
--- a/quickstep/src/com/android/quickstep/views/TaskContainer.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
@@ -38,8 +38,7 @@
 class TaskContainer(
     val taskView: TaskView,
     val task: Task,
-    val thumbnailView: TaskThumbnailView?,
-    val thumbnailViewDeprecated: TaskThumbnailViewDeprecated,
+    val snapshotView: View,
     val iconView: TaskViewIcon,
     /**
      * This technically can be a vanilla [android.view.TouchDelegate] class, however that class
@@ -57,12 +56,29 @@
     val overlay: TaskOverlayFactory.TaskOverlay<*> = taskOverlayFactory.createOverlay(this)
     val taskContainerData = TaskContainerData()
 
-    val snapshotView: View
-        get() = thumbnailView ?: thumbnailViewDeprecated
+    init {
+        if (enableRefactorTaskThumbnail()) {
+            require(snapshotView is TaskThumbnailView)
+        } else {
+            require(snapshotView is TaskThumbnailViewDeprecated)
+        }
+    }
+
+    val thumbnailView: TaskThumbnailView
+        get() {
+            require(enableRefactorTaskThumbnail())
+            return snapshotView as TaskThumbnailView
+        }
+
+    val thumbnailViewDeprecated: TaskThumbnailViewDeprecated
+        get() {
+            require(!enableRefactorTaskThumbnail())
+            return snapshotView as TaskThumbnailViewDeprecated
+        }
 
     // TODO(b/349120849): Extract ThumbnailData from TaskContainerData/TaskThumbnailViewModel
     val thumbnail: Bitmap?
-        get() = thumbnailViewDeprecated.thumbnail
+        get() = if (enableRefactorTaskThumbnail()) null else thumbnailViewDeprecated.thumbnail
 
     // TODO(b/334826842): Support shouldShowSplashView for new TTV.
     val shouldShowSplashView: Boolean
@@ -100,13 +116,14 @@
 
     fun destroy() {
         digitalWellBeingToast?.destroy()
-        thumbnailView?.let { taskView.removeView(it) }
+        if (enableRefactorTaskThumbnail()) {
+            taskView.removeView(thumbnailView)
+        }
         overlay.destroy()
     }
 
     fun bind() {
-        if (enableRefactorTaskThumbnail() && thumbnailView != null) {
-            thumbnailViewDeprecated.setTaskOverlay(overlay)
+        if (enableRefactorTaskThumbnail()) {
             bindThumbnailView()
             overlay.init()
         } else {
@@ -119,7 +136,7 @@
     fun bindThumbnailView() {
         // TODO(b/343364498): Existing view has shouldShowScreenshot as an override as well but
         //  this should be decided inside TaskThumbnailViewModel.
-        thumbnailView?.viewModel?.bind(TaskThumbnail(task.key.id, taskView.isRunningTask))
+        thumbnailView.viewModel.bind(TaskThumbnail(task.key.id, taskView.isRunningTask))
     }
 
     fun setOverlayEnabled(enabled: Boolean) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
index 5b7e6c7..56ca043 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java
@@ -165,17 +165,6 @@
     }
 
     /**
-     * Sets TaskOverlay without binding a task.
-     *
-     * @deprecated Should only be used when using new
-     * {@link com.android.quickstep.task.thumbnail.TaskThumbnailView}.
-     */
-    @Deprecated
-    public void setTaskOverlay(TaskOverlay<?> overlay) {
-        mOverlay = overlay;
-    }
-
-    /**
      * Updates the thumbnail.
      *
      * @param refreshNow whether the {@code thumbnailData} will be used to redraw immediately.
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 9977d30..2e07e36 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -102,7 +102,8 @@
     defStyleAttr: Int = 0,
     defStyleRes: Int = 0,
     focusBorderAnimator: BorderAnimator? = null,
-    hoverBorderAnimator: BorderAnimator? = null
+    hoverBorderAnimator: BorderAnimator? = null,
+    type: TaskViewType = TaskViewType.SINGLE
 ) : FrameLayout(context, attrs), ViewPool.Reusable {
     /**
      * Used in conjunction with [onTaskListVisibilityChanged], providing more granularity on which
@@ -112,18 +113,7 @@
     @IntDef(FLAG_UPDATE_ALL, FLAG_UPDATE_ICON, FLAG_UPDATE_THUMBNAIL, FLAG_UPDATE_CORNER_RADIUS)
     annotation class TaskDataChanges
 
-    /** Type of task view */
-    @Retention(AnnotationRetention.SOURCE)
-    @IntDef(Type.SINGLE, Type.GROUPED, Type.DESKTOP)
-    annotation class Type {
-        companion object {
-            const val SINGLE = 1
-            const val GROUPED = 2
-            const val DESKTOP = 3
-        }
-    }
-
-    val taskViewData = TaskViewData()
+    val taskViewData = TaskViewData(type)
     val taskIds: IntArray
         /** Returns a copy of integer array containing taskIds of all tasks in the TaskView. */
         get() = taskContainers.map { it.task.key.id }.toIntArray()
@@ -671,24 +661,22 @@
         taskOverlayFactory: TaskOverlayFactory
     ): TaskContainer {
         val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = findViewById(thumbnailViewId)!!
-        val thumbnailView: TaskThumbnailView?
-        if (enableRefactorTaskThumbnail()) {
-            val indexOfSnapshotView = indexOfChild(thumbnailViewDeprecated)
-            thumbnailView =
+        val snapshotView =
+            if (enableRefactorTaskThumbnail()) {
+                thumbnailViewDeprecated.visibility = GONE
+                val indexOfSnapshotView = indexOfChild(thumbnailViewDeprecated)
                 TaskThumbnailView(context).apply {
                     layoutParams = thumbnailViewDeprecated.layoutParams
                     addView(this, indexOfSnapshotView)
                 }
-            thumbnailViewDeprecated.visibility = GONE
-        } else {
-            thumbnailView = null
-        }
+            } else {
+                thumbnailViewDeprecated
+            }
         val iconView = getOrInflateIconView(iconViewId)
         return TaskContainer(
             this,
             task,
-            thumbnailView,
-            thumbnailViewDeprecated,
+            snapshotView,
             iconView,
             TransformingTouchDelegate(iconView.asView()),
             stagePosition,
@@ -710,8 +698,6 @@
                 .inflate() as TaskViewIcon
     }
 
-    protected fun isTaskContainersInitialized() = this::taskContainers.isInitialized
-
     fun containsMultipleTasks() = taskContainers.size > 1
 
     /**
diff --git a/quickstep/src/com/android/quickstep/views/TaskViewType.kt b/quickstep/src/com/android/quickstep/views/TaskViewType.kt
new file mode 100644
index 0000000..b2a32a9
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/TaskViewType.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.quickstep.views
+
+/** Type of the [TaskView] */
+enum class TaskViewType {
+    SINGLE,
+    GROUPED,
+    DESKTOP
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
index a394b65..b78f871 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelTest.kt
@@ -30,6 +30,7 @@
 import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
 import com.android.quickstep.task.viewmodel.TaskContainerData
 import com.android.quickstep.task.viewmodel.TaskViewData
+import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.recents.model.ThumbnailData
 import com.google.common.truth.Truth.assertThat
@@ -42,12 +43,14 @@
 
 @RunWith(AndroidJUnit4::class)
 class TaskThumbnailViewModelTest {
+    private var taskViewType = TaskViewType.SINGLE
     private val recentsViewData = RecentsViewData()
-    private val taskViewData = TaskViewData()
+    private val taskViewData by lazy { TaskViewData(taskViewType) }
     private val taskContainerData = TaskContainerData()
     private val tasksRepository = FakeTasksRepository()
-    private val systemUnderTest =
+    private val systemUnderTest by lazy {
         TaskThumbnailViewModel(recentsViewData, taskViewData, taskContainerData, tasksRepository)
+    }
 
     private val tasks = (0..5).map(::createTaskWithId)
 
@@ -66,14 +69,26 @@
     }
 
     @Test
-    fun setRecentsFullscreenProgress_thenProgressIsPassedThrough() = runTest {
+    fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsPassedThrough() = runTest {
         recentsViewData.fullscreenProgress.value = 0.5f
 
-        assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.5f)
+        assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.5f)
 
         recentsViewData.fullscreenProgress.value = 0.6f
 
-        assertThat(systemUnderTest.recentsFullscreenProgress.first()).isEqualTo(0.6f)
+        assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.6f)
+    }
+
+    @Test
+    fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsConstantForDesktop() = runTest {
+        taskViewType = TaskViewType.DESKTOP
+        recentsViewData.fullscreenProgress.value = 0.5f
+
+        assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
+
+        recentsViewData.fullscreenProgress.value = 0.6f
+
+        assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
     }
 
     @Test
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
index a6d3887..f11cd0b 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/GroupTaskTest.kt
@@ -21,7 +21,7 @@
 import android.graphics.Rect
 import com.android.launcher3.util.LauncherMultivalentJUnit
 import com.android.launcher3.util.SplitConfigurationOptions
-import com.android.quickstep.views.TaskView
+import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.Task
 import com.android.wm.shell.common.split.SplitScreenConstants
 import com.google.common.truth.Truth.assertThat
@@ -68,8 +68,8 @@
                 2,
                 SplitScreenConstants.SNAP_TO_50_50
             )
-        val task1 = GroupTask(createTask(1), createTask(2), splitBounds, TaskView.Type.GROUPED)
-        val task2 = GroupTask(createTask(1), createTask(2), splitBounds, TaskView.Type.GROUPED)
+        val task1 = GroupTask(createTask(1), createTask(2), splitBounds, TaskViewType.GROUPED)
+        val task2 = GroupTask(createTask(1), createTask(2), splitBounds, TaskViewType.GROUPED)
         assertThat(task1).isEqualTo(task2)
     }
 
@@ -91,15 +91,15 @@
                 2,
                 SplitScreenConstants.SNAP_TO_30_70
             )
-        val task1 = GroupTask(createTask(1), createTask(2), splitBounds1, TaskView.Type.GROUPED)
-        val task2 = GroupTask(createTask(1), createTask(2), splitBounds2, TaskView.Type.GROUPED)
+        val task1 = GroupTask(createTask(1), createTask(2), splitBounds1, TaskViewType.GROUPED)
+        val task2 = GroupTask(createTask(1), createTask(2), splitBounds2, TaskViewType.GROUPED)
         assertThat(task1).isNotEqualTo(task2)
     }
 
     @Test
     fun testGroupTask_differentType_isNotEqual() {
-        val task1 = GroupTask(createTask(1), null, null, TaskView.Type.SINGLE)
-        val task2 = GroupTask(createTask(1), null, null, TaskView.Type.DESKTOP)
+        val task1 = GroupTask(createTask(1), null, null, TaskViewType.SINGLE)
+        val task2 = GroupTask(createTask(1), null, null, TaskViewType.DESKTOP)
         assertThat(task1).isNotEqualTo(task2)
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
index 61a5b44..d9d5585 100644
--- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -191,7 +191,6 @@
         return TaskContainer(
             taskView,
             task,
-            thumbnailView = null,
             thumbnailViewDeprecated,
             iconView,
             transformingTouchDelegate,
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index ce16b70..5d00255 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -32,7 +32,7 @@
 
 import com.android.launcher3.util.LooperExecutor;
 import com.android.quickstep.util.GroupTask;
-import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskViewType;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 
@@ -125,7 +125,7 @@
                 Integer.MAX_VALUE /* numTasks */, -1 /* requestId */, false /* loadKeysOnly */);
 
         assertEquals(1, taskList.size());
-        assertEquals(TaskView.Type.DESKTOP, taskList.get(0).taskViewType);
+        assertEquals(TaskViewType.DESKTOP, taskList.get(0).taskViewType);
         List<Task> actualFreeformTasks = taskList.get(0).getTasks();
         assertEquals(3, actualFreeformTasks.size());
         assertEquals(1, actualFreeformTasks.get(0).key.id);