Util classes for the Taskbar Customization Framework
Test: Presubmit
Bug: 341146605
Flag: NONE Taskbar Customization
Change-Id: Ice9d2e6db2754ba75a1253da45dd28aa63cad58f
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
index 0946caf..b1fc9cc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarRecentAppsController.kt
@@ -46,8 +46,11 @@
enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()
// TODO(b/343532825): Add a setting to disable Recents even when the flag is on.
- @VisibleForTesting
- var isEnabled = enableRecentsInTaskbar() || canShowRunningApps
+ var isEnabled: Boolean = enableRecentsInTaskbar() || canShowRunningApps
+ @VisibleForTesting
+ set(isEnabledFromTest){
+ field = isEnabledFromTest
+ }
// Initialized in init.
private lateinit var controllers: TaskbarControllers
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.kt
new file mode 100644
index 0000000..3c4b63a
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarContainer.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 TaskbarContainer {
+ 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
new file mode 100644
index 0000000..1ec075f
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarFeatureEvaluator.kt
@@ -0,0 +1,44 @@
+/*
+ * 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
+
+import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
+import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.taskbar.TaskbarControllers
+import com.android.launcher3.taskbar.TaskbarRecentAppsController
+import com.android.launcher3.util.DisplayController
+
+/** Evaluates all the features taskbar can have. */
+class TaskbarFeatureEvaluator(
+ private val taskbarActivityContext: TaskbarActivityContext,
+ private val taskbarControllers: TaskbarControllers,
+) {
+
+ val hasAllApps = true
+ val hasAppIcons = true
+ val hasBubbles = false
+ val hasNavButtons = taskbarActivityContext.isThreeButtonNav
+
+ val hasRecents: Boolean
+ get() = taskbarControllers.taskbarRecentAppsController.isEnabled
+
+ val hasDivider: Boolean
+ get() = enableTaskbarPinning() || hasRecents
+
+ 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
new file mode 100644
index 0000000..4cd895d
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarIconSpecs.kt
@@ -0,0 +1,41 @@
+/*
+ * 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
+
+/** Taskbar Icon Specs */
+object TaskbarIconSpecs {
+
+ val iconSize40dp = TaskbarIconSize(40)
+ val iconSize44dp = TaskbarIconSize(44)
+ val iconSize48dp = TaskbarIconSize(48)
+ val iconSize52dp = TaskbarIconSize(52)
+
+ val transientTaskbarIconSizes = arrayOf(iconSize44dp, iconSize48dp, iconSize52dp)
+
+ val defaultPersistentIconSize = iconSize40dp
+ val defaultTransientIconSize = iconSize44dp
+
+ // defined as row, columns
+ val transientTaskbarIconSizeByGridSize =
+ mapOf(
+ Pair(6, 5) to iconSize52dp,
+ Pair(4, 5) to iconSize48dp,
+ Pair(5, 4) to iconSize48dp,
+ Pair(4, 4) to iconSize48dp,
+ Pair(5, 6) to iconSize44dp,
+ )
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt
new file mode 100644
index 0000000..02e5947
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarSpecsEvaluator.kt
@@ -0,0 +1,60 @@
+/*
+ * 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
+
+/** Evaluates the taskbar specs based on the taskbar grid size and the taskbar icon size. */
+class TaskbarSpecsEvaluator(private val taskbarFeatureEvaluator: TaskbarFeatureEvaluator) {
+
+ fun getIconSizeByGrid(row: Int, column: Int): TaskbarIconSize {
+ return if (taskbarFeatureEvaluator.isTransient) {
+ TaskbarIconSpecs.transientTaskbarIconSizeByGridSize.getOrDefault(
+ Pair(row, column),
+ TaskbarIconSpecs.defaultTransientIconSize,
+ )
+ } else {
+ TaskbarIconSpecs.defaultPersistentIconSize
+ }
+ }
+
+ fun getIconSizeStepDown(iconSize: TaskbarIconSize): TaskbarIconSize {
+ if (!taskbarFeatureEvaluator.isTransient) return TaskbarIconSpecs.defaultPersistentIconSize
+
+ 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]
+ }
+
+ fun getIconSizeStepUp(iconSize: TaskbarIconSize): TaskbarIconSize {
+ if (!taskbarFeatureEvaluator.isTransient) return TaskbarIconSpecs.defaultPersistentIconSize
+
+ val currentIconSizeIndex = TaskbarIconSpecs.transientTaskbarIconSizes.indexOf(iconSize)
+ // return the current icon size if supplied icon size is unknown or we have reached the
+ // max icon size.
+ return if (
+ currentIconSizeIndex == -1 ||
+ currentIconSizeIndex == TaskbarIconSpecs.transientTaskbarIconSizes.size - 1
+ ) {
+ iconSize
+ } else {
+ TaskbarIconSpecs.transientTaskbarIconSizes.get(currentIconSizeIndex + 1)
+ }
+ }
+}
+
+data class TaskbarIconSize(val size: Int)
diff --git a/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt
new file mode 100644
index 0000000..b637e7d
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/taskbar/customization/TaskbarSpecsEvaluatorTest.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.taskbar.customization
+
+import com.android.launcher3.taskbar.customization.TaskbarFeatureEvaluator
+import com.android.launcher3.taskbar.customization.TaskbarIconSpecs
+import com.android.launcher3.taskbar.customization.TaskbarSpecsEvaluator
+import com.android.launcher3.util.LauncherMultivalentJUnit
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+@RunWith(LauncherMultivalentJUnit::class)
+class TaskbarSpecsEvaluatorTest {
+
+ private val taskbarFeatureEvaluator = mock<TaskbarFeatureEvaluator>()
+ private val taskbarSpecsEvaluator = spy(TaskbarSpecsEvaluator(taskbarFeatureEvaluator))
+
+ @Test
+ fun testGetIconSizeByGrid_whenTaskbarIsTransient_withValidRowAndColumn() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(6, 5))
+ .isEqualTo(TaskbarIconSpecs.iconSize52dp)
+ }
+
+ @Test
+ fun testGetIconSizeByGrid_whenTaskbarIsTransient_withInvalidRowAndColumn() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(1, 2))
+ .isEqualTo(TaskbarIconSpecs.defaultTransientIconSize)
+ }
+
+ @Test
+ fun testGetIconSizeByGrid_whenTaskbarIsPersistent() {
+ doReturn(false).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeByGrid(6, 5))
+ .isEqualTo(TaskbarIconSpecs.defaultPersistentIconSize)
+ }
+
+ @Test
+ fun testGetIconSizeStepDown_whenTaskbarIsPersistent() {
+ doReturn(false).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize44dp))
+ .isEqualTo(TaskbarIconSpecs.defaultPersistentIconSize)
+ }
+
+ @Test
+ fun testGetIconSizeStepDown_whenTaskbarIsTransientAndIconSizeAreInBound() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize52dp))
+ .isEqualTo(TaskbarIconSpecs.iconSize48dp)
+ }
+
+ @Test
+ fun testGetIconSizeStepDown_whenTaskbarIsTransientAndIconSizeAreOutOfBound() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepDown(TaskbarIconSpecs.iconSize44dp))
+ .isEqualTo(TaskbarIconSpecs.iconSize44dp)
+ }
+
+ @Test
+ fun testGetIconSizeStepUp_whenTaskbarIsPersistent() {
+ doReturn(false).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize40dp))
+ .isEqualTo(TaskbarIconSpecs.iconSize40dp)
+ }
+
+ @Test
+ fun testGetIconSizeStepUp_whenTaskbarIsTransientAndIconSizeAreInBound() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize44dp))
+ .isEqualTo(TaskbarIconSpecs.iconSize48dp)
+ }
+
+ @Test
+ fun testGetIconSizeStepUp_whenTaskbarIsTransientAndIconSizeAreOutOfBound() {
+ doReturn(true).whenever(taskbarFeatureEvaluator).isTransient
+ assertThat(taskbarSpecsEvaluator.getIconSizeStepUp(TaskbarIconSpecs.iconSize52dp))
+ .isEqualTo(TaskbarIconSpecs.iconSize52dp)
+ }
+}