Add support for different container and space calculation logic.

This CL includes
	- Taskbar container enum class and interface for container to calculate their space needed.
        - Inits and getter of util classes in taksbar activity context.
        - Taskbar Icons specs not have default margins and minimum touch target specs
	- Updates to the test
        - Logic for calculating the space needed for taskbar container

Test: Presubmit
Bug: 341146605
Flag: com.android.launcher3.enable_taskbar_customization
Change-Id: I89e9d521476902a9027f6fd0cebdc2690b2e5f31
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 21a8268..3481e52 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -109,6 +109,8 @@
 import com.android.launcher3.taskbar.bubbles.BubblePinController;
 import com.android.launcher3.taskbar.bubbles.BubbleStashController;
 import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
+import com.android.launcher3.taskbar.customization.TaskbarFeatureEvaluator;
+import com.android.launcher3.taskbar.customization.TaskbarSpecsEvaluator;
 import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
 import com.android.launcher3.testing.TestLogging;
@@ -202,6 +204,10 @@
 
     private final LauncherPrefs mLauncherPrefs;
 
+    private final TaskbarFeatureEvaluator mTaskbarFeatureEvaluator;
+
+    private final TaskbarSpecsEvaluator mTaskbarSpecsEvaluator;
+
     public TaskbarActivityContext(Context windowContext,
             @Nullable Context navigationBarPanelContext, DeviceProfile launcherDp,
             TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
@@ -212,6 +218,13 @@
         applyDeviceProfile(launcherDp);
         final Resources resources = getResources();
 
+        mTaskbarFeatureEvaluator = TaskbarFeatureEvaluator.getInstance(this);
+        mTaskbarSpecsEvaluator = new TaskbarSpecsEvaluator(
+                this,
+                mTaskbarFeatureEvaluator,
+                mDeviceProfile.inv.numRows,
+                mDeviceProfile.inv.numColumns);
+
         mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false);
         mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
                 () -> getPackageManager().isSafeMode());
@@ -1608,6 +1621,14 @@
         return mControllers.taskbarStashController.isInStashedLauncherState();
     }
 
+    public TaskbarFeatureEvaluator getTaskbarFeatureEvaluator() {
+        return mTaskbarFeatureEvaluator;
+    }
+
+    public TaskbarSpecsEvaluator getTaskbarSpecsEvaluator() {
+        return mTaskbarSpecsEvaluator;
+    }
+
     protected void dumpLogs(String prefix, PrintWriter pw) {
         pw.println(prefix + "TaskbarActivityContext:");
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt
index 3c4b63a..35ae43c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt
@@ -13,15 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.android.launcher3.taskbar.customization
 
-/** Enums for all feature container that taskbar supports. */
-enum class TaskbarContainer {
-    ALL_APPS,
-    DIVIDER,
-    APP_ICONS,
-    RECENTS,
-    NAV_BUTTONS,
-    BUBBLES,
+import androidx.annotation.Dimension
+
+/**
+ * Interface to be implemented by all taskbar container to expose [spaceNeeded] for each container.
+ */
+interface TaskbarContainer {
+    @get:Dimension(unit = Dimension.DP) val spaceNeeded: Int
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainers.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainers.kt
new file mode 100644
index 0000000..d4548f5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainers.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.launcher3.taskbar.customization
+
+/** Enums for all feature container that taskbar supports. */
+enum class TaskbarContainers {
+    ALL_APPS,
+    DIVIDER,
+    APP_ICONS,
+    RECENTS,
+    NAV_BUTTONS,
+    BUBBLES,
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
index ac7dd06..c83ac50 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
@@ -16,27 +16,43 @@
 
 package com.android.launcher3.taskbar.customization
 
+import com.android.launcher3.Flags.enableRecentsInTaskbar
 import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
 import com.android.launcher3.taskbar.TaskbarActivityContext
-import com.android.launcher3.taskbar.TaskbarControllers
 import com.android.launcher3.util.DisplayController
 
 /** Evaluates all the features taskbar can have. */
-class TaskbarFeatureEvaluator(
+class TaskbarFeatureEvaluator
+private constructor(
     private val taskbarActivityContext: TaskbarActivityContext,
-    private val taskbarControllers: TaskbarControllers,
 ) {
 
+    companion object {
+        @Volatile private lateinit var taskbarFeatureEvaluator: TaskbarFeatureEvaluator
+
+        @JvmStatic
+        fun getInstance(
+            taskbarActivityContext: TaskbarActivityContext,
+        ): TaskbarFeatureEvaluator {
+            synchronized(this) {
+                if (!::taskbarFeatureEvaluator.isInitialized) {
+                    taskbarFeatureEvaluator = TaskbarFeatureEvaluator(taskbarActivityContext)
+                }
+                return taskbarFeatureEvaluator
+            }
+        }
+    }
+
     val hasAllApps = true
     val hasAppIcons = true
     val hasBubbles = false
     val hasNavButtons = taskbarActivityContext.isThreeButtonNav
 
-    val hasRecents: Boolean
-        get() = taskbarControllers.taskbarRecentAppsController.shownTasks.isNotEmpty()
+    val isRecentsEnabled: Boolean
+        get() = enableRecentsInTaskbar()
 
     val hasDivider: Boolean
-        get() = enableTaskbarPinning() || hasRecents
+        get() = enableTaskbarPinning() || isRecentsEnabled
 
     val isTransient: Boolean
         get() = DisplayController.isTransientTaskbar(taskbarActivityContext)
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt
index 67bbcce..887eb01 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt
@@ -29,6 +29,13 @@
     val defaultPersistentIconSize = iconSize40dp
     val defaultTransientIconSize = iconSize44dp
 
+    val minimumIconSize = iconSize40dp
+
+    val defaultPersistentIconMargin = TaskbarIconMarginSize(6)
+    val defaultTransientIconMargin = TaskbarIconMarginSize(12)
+
+    val minimumTaskbarIconTouchSize = TaskbarIconSize(48)
+
     val transientTaskbarIconSizeByGridSize =
         mapOf(
             TransientTaskbarIconSizeKey(6, 5, false) to iconSize52dp,
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt
index 0b7be40..761b47e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt
@@ -16,8 +16,33 @@
 
 package com.android.launcher3.taskbar.customization
 
+import com.android.launcher3.taskbar.TaskbarActivityContext
+
 /** Evaluates the taskbar specs based on the taskbar grid size and the taskbar icon size. */
-class TaskbarSpecsEvaluator(private val taskbarFeatureEvaluator: TaskbarFeatureEvaluator) {
+class TaskbarSpecsEvaluator(
+    private val taskbarActivityContext: TaskbarActivityContext,
+    private val taskbarFeatureEvaluator: TaskbarFeatureEvaluator,
+    numRows: Int = taskbarActivityContext.deviceProfile.inv.numRows,
+    numColumns: Int = taskbarActivityContext.deviceProfile.inv.numColumns,
+) {
+    var taskbarIconSize: TaskbarIconSize = getIconSizeByGrid(numRows, numColumns)
+
+    // TODO(b/341146605) : initialize it to taskbar container in later cl.
+    private var taskbarContainer: List<TaskbarContainer> = emptyList()
+
+    val taskbarIconPadding: Int =
+        if (TaskbarIconSpecs.minimumTaskbarIconTouchSize.size > taskbarIconSize.size) {
+            (TaskbarIconSpecs.minimumTaskbarIconTouchSize.size - taskbarIconSize.size) / 2
+        } else {
+            0
+        }
+
+    val taskbarIconMargin: TaskbarIconMarginSize =
+        if (taskbarFeatureEvaluator.isTransient) {
+            TaskbarIconSpecs.defaultTransientIconMargin
+        } else {
+            TaskbarIconSpecs.defaultPersistentIconMargin
+        }
 
     fun getIconSizeByGrid(row: Int, column: Int): TaskbarIconSize {
         return if (taskbarFeatureEvaluator.isTransient) {
@@ -36,8 +61,11 @@
         val currentIconSizeIndex = TaskbarIconSpecs.transientTaskbarIconSizes.indexOf(iconSize)
         // return the current icon size if supplied icon size is unknown or we have reached the
         // min icon size.
-        return if (currentIconSizeIndex == -1 || currentIconSizeIndex == 0) iconSize
-        else TaskbarIconSpecs.transientTaskbarIconSizes[currentIconSizeIndex - 1]
+        return if (currentIconSizeIndex == -1 || currentIconSizeIndex == 0) {
+            iconSize
+        } else {
+            TaskbarIconSpecs.transientTaskbarIconSizes[currentIconSizeIndex - 1]
+        }
     }
 
     fun getIconSizeStepUp(iconSize: TaskbarIconSize): TaskbarIconSize {
@@ -52,11 +80,28 @@
         ) {
             iconSize
         } else {
-            TaskbarIconSpecs.transientTaskbarIconSizes.get(currentIconSizeIndex + 1)
+            TaskbarIconSpecs.transientTaskbarIconSizes[currentIconSizeIndex + 1]
         }
     }
+
+    // TODO(jagrutdesai) : Call this in init once the containers are ready.
+    private fun calculateTaskbarIconSize() {
+        while (
+            taskbarIconSize != TaskbarIconSpecs.minimumIconSize &&
+                taskbarActivityContext.transientTaskbarBounds.width() <
+                    calculateSpaceNeeded(taskbarContainer)
+        ) {
+            taskbarIconSize = getIconSizeStepDown(taskbarIconSize)
+        }
+    }
+
+    private fun calculateSpaceNeeded(containers: List<TaskbarContainer>): Int {
+        return containers.sumOf { it.spaceNeeded }
+    }
 }
 
 data class TaskbarIconSize(val size: Int)
 
 data class TransientTaskbarIconSizeKey(val row: Int, val column: Int, val isLandscape: Boolean)
+
+data class TaskbarIconMarginSize(val size: Int)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt
index 0bf68eb..d66197a 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.taskbar.customization
 
+import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.launcher3.taskbar.customization.TaskbarFeatureEvaluator
 import com.android.launcher3.taskbar.customization.TaskbarIconSpecs
 import com.android.launcher3.taskbar.customization.TaskbarSpecsEvaluator
@@ -32,7 +33,9 @@
 class TaskbarSpecsEvaluatorTest {
 
     private val taskbarFeatureEvaluator = mock<TaskbarFeatureEvaluator>()
-    private val taskbarSpecsEvaluator = spy(TaskbarSpecsEvaluator(taskbarFeatureEvaluator))
+    private val taskbarActivityContext = mock<TaskbarActivityContext>()
+    private var taskbarSpecsEvaluator =
+        spy(TaskbarSpecsEvaluator(taskbarActivityContext, taskbarFeatureEvaluator, 0, 0))
 
     @Test
     fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumnInLandscape() {