Updating ThemeManager to be extendible

Moving the themeController inside the iconState object

Bug: 381897614
Test: atest ThemeManagerTest
Flag: EXEMPT refactor
Change-Id: I190be0af3202e97808f5dbda30ad0ca811581881
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d3684b2..fb847f9 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -77,7 +77,6 @@
 import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.graphics.PreloadIconDrawable;
-import com.android.launcher3.graphics.ThemeManager;
 import com.android.launcher3.icons.DotRenderer;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
@@ -484,9 +483,7 @@
     }
 
     private void setNonPendingIcon(ItemInfoWithIcon info) {
-        ThemeManager themeManager = ThemeManager.INSTANCE.get(getContext());
-        int flags = (shouldUseTheme()
-                && themeManager.isMonoThemeEnabled()) ? FLAG_THEMED : 0;
+        int flags = shouldUseTheme() ? FLAG_THEMED : 0;
         // Remove badge on icons smaller than 48dp.
         if (mHideBadge || mDisplay == DISPLAY_SEARCH_RESULT_SMALL) {
             flags |= FLAG_NO_BADGE;
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index d93c07f..cb3a0bc 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -658,9 +658,9 @@
                         appState.getInvariantDeviceProfile().fillResIconDpi);
                 // Only fetch badge if the icon is on workspace
                 if (info.id != ItemInfo.NO_ID && badge == null) {
-                    badge = appState.getIconCache().getShortcutInfoBadge(si)
-                            .newIcon(context, ThemeManager.INSTANCE.get(context)
-                                    .isMonoThemeEnabled() ? FLAG_THEMED : 0);
+                    badge = appState.getIconCache().getShortcutInfoBadge(si).newIcon(
+                            context, ThemeManager.INSTANCE.get(context).isIconThemeEnabled()
+                                    ? FLAG_THEMED : 0);
                 }
             }
         } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
diff --git a/src/com/android/launcher3/graphics/ThemeManager.kt b/src/com/android/launcher3/graphics/ThemeManager.kt
index 9f35e4a..242220a 100644
--- a/src/com/android/launcher3/graphics/ThemeManager.kt
+++ b/src/com/android/launcher3/graphics/ThemeManager.kt
@@ -40,8 +40,8 @@
 open class ThemeManager
 @Inject
 constructor(
-    @ApplicationContext private val context: Context,
-    private val prefs: LauncherPrefs,
+    @ApplicationContext protected val context: Context,
+    protected val prefs: LauncherPrefs,
     lifecycle: DaggerSingletonTracker,
 ) {
 
@@ -53,9 +53,11 @@
         set(value) = prefs.put(THEMED_ICONS, value)
         get() = prefs.get(THEMED_ICONS)
 
-    var themeController: IconThemeController? =
-        if (isMonoThemeEnabled) MonoIconThemeController() else null
-        private set
+    val themeController: IconThemeController?
+        get() = iconState.themeController
+
+    val isIconThemeEnabled: Boolean
+        get() = themeController != null
 
     private val listeners = CopyOnWriteArrayList<ThemeChangeListener>()
 
@@ -77,12 +79,10 @@
         }
     }
 
-    private fun verifyIconState() {
+    protected fun verifyIconState() {
         val newState = parseIconState()
         if (newState == iconState) return
-
         iconState = newState
-        themeController = if (isMonoThemeEnabled) MonoIconThemeController() else null
 
         listeners.forEach { it.onThemeChanged() }
     }
@@ -105,15 +105,19 @@
         return IconState(
             iconMask = iconMask,
             folderShapeMask = shapeModel?.folderPathString ?: iconMask,
-            isMonoTheme = isMonoThemeEnabled,
+            themeController = createThemeController(),
         )
     }
 
+    protected open fun createThemeController(): IconThemeController? {
+        return if (isMonoThemeEnabled) MONO_THEME_CONTROLLER else null
+    }
+
     data class IconState(
         val iconMask: String,
         val folderShapeMask: String,
-        val isMonoTheme: Boolean,
-        val themeCode: String = if (isMonoTheme) "with-theme" else "no-theme",
+        val themeController: IconThemeController?,
+        val themeCode: String = themeController?.themeID ?: "no-theme",
     ) {
         fun toUniqueId() = "${iconMask.hashCode()},$themeCode"
     }
@@ -135,5 +139,8 @@
         private const val ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED"
         private val CONFIG_ICON_MASK_RES_ID: Int =
             Resources.getSystem().getIdentifier("config_icon_mask", "string", "android")
+
+        // Use a constant to allow equality check in verifyIconState
+        private val MONO_THEME_CONTROLLER = MonoIconThemeController()
     }
 }
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index 7fb0152..ff40f30 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -323,7 +323,7 @@
      * Returns a FastBitmapDrawable with the icon and context theme applied
      */
     public FastBitmapDrawable newIcon(Context context, @DrawableCreationFlags int creationFlags) {
-        if (!ThemeManager.INSTANCE.get(context).isMonoThemeEnabled()) {
+        if (!ThemeManager.INSTANCE.get(context).isIconThemeEnabled()) {
             creationFlags &= ~FLAG_THEMED;
         }
         FastBitmapDrawable drawable = bitmap.newIcon(context, creationFlags);
diff --git a/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt b/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt
index 43b7b68..85c1156 100644
--- a/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt
@@ -21,11 +21,13 @@
 import com.android.launcher3.FakeLauncherPrefs
 import com.android.launcher3.dagger.LauncherAppComponent
 import com.android.launcher3.dagger.LauncherAppSingleton
+import com.android.launcher3.icons.mono.MonoIconThemeController
 import com.android.launcher3.util.AllModulesForTest
 import com.android.launcher3.util.Executors.MAIN_EXECUTOR
 import com.android.launcher3.util.FakePrefsModule
 import com.android.launcher3.util.SandboxApplication
 import com.android.launcher3.util.TestUtil
+import com.google.common.truth.Truth.assertThat
 import dagger.Component
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
@@ -55,12 +57,13 @@
         themeManager.isMonoThemeEnabled = true
         TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {}
         assertTrue(themeManager.isMonoThemeEnabled)
-        assertTrue(themeManager.iconState.isMonoTheme)
+        assertThat(themeManager.iconState.themeController)
+            .isInstanceOf(MonoIconThemeController::class.java)
 
         themeManager.isMonoThemeEnabled = false
         TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {}
         assertFalse(themeManager.isMonoThemeEnabled)
-        assertFalse(themeManager.iconState.isMonoTheme)
+        assertThat(themeManager.iconState.themeController).isNull()
     }
 
     @Test