Add monochrome to wallpaper colors

Add monochrome to second position of wallpaper colors in revamped UI.

Bug: 273552158
Test: Manually verified
Change-Id: I79d792a8de779a29da9a19a442b5e88b3017b666
diff --git a/src/com/android/customization/model/color/ColorProvider.kt b/src/com/android/customization/model/color/ColorProvider.kt
index 6ce6f0b..6520b52 100644
--- a/src/com/android/customization/model/color/ColorProvider.kt
+++ b/src/com/android/customization/model/color/ColorProvider.kt
@@ -67,6 +67,10 @@
             arrayOf(Style.TONAL_SPOT, Style.SPRITZ, Style.VIBRANT, Style.EXPRESSIVE)
         else arrayOf(Style.TONAL_SPOT)
 
+    private val monochromeEnabled =
+        InjectorProvider.getInjector().getFlags().isMonochromaticThemeEnabled(mContext)
+    private var monochromeBundleName: String? = null
+
     private val scope =
         if (mContext is LifecycleOwner) {
             mContext.lifecycleScope
@@ -177,6 +181,21 @@
         }
 
         if (shouldUseRevampedUi) {
+            // Insert monochrome in the second position if it is enabled and included in preset
+            // colors
+            if (monochromeEnabled) {
+                monochromeBundleName?.let {
+                    bundles.add(
+                        1,
+                        buildRevampedUIPreset(
+                            it,
+                            -1,
+                            Style.MONOCHROMATIC,
+                            ColorType.WALLPAPER_COLOR
+                        )
+                    )
+                }
+            }
             bundles.addAll(
                 colorBundles?.filterNot {
                     (it as ColorOptionImpl).type == ColorType.WALLPAPER_COLOR
@@ -214,13 +233,13 @@
         shouldUseRevampedUi: Boolean,
     ) {
         // TODO(b/202145216): Measure time cost in the loop.
-        for (style in styleList) {
-            val lightColorScheme = ColorScheme(colorInt, /* darkTheme= */ false, style)
-            val darkColorScheme = ColorScheme(colorInt, /* darkTheme= */ true, style)
-            if (shouldUseRevampedUi) {
+        if (shouldUseRevampedUi) {
+            for (style in styleList) {
+                val lightColorScheme = ColorScheme(colorInt, /* darkTheme= */ false, style)
+                val darkColorScheme = ColorScheme(colorInt, /* darkTheme= */ true, style)
                 val builder = ColorOptionImpl.Builder()
-                builder.lightColors = lightColorScheme.getRevampedUILightColorPreview()
-                builder.darkColors = darkColorScheme.getRevampedUIDarkColorPreview()
+                builder.lightColors = getRevampedUILightColorPreview(lightColorScheme)
+                builder.darkColors = getRevampedUIDarkColorPreview(darkColorScheme)
                 builder.addOverlayPackage(
                     OVERLAY_CATEGORY_SYSTEM_PALETTE,
                     if (isDefault) "" else toColorString(colorInt)
@@ -232,7 +251,11 @@
                 builder.isDefault = isDefault
                 builder.type = ColorType.WALLPAPER_COLOR
                 bundles.add(builder.build())
-            } else {
+            }
+        } else {
+            for (style in styleList) {
+                val lightColorScheme = ColorScheme(colorInt, /* darkTheme= */ false, style)
+                val darkColorScheme = ColorScheme(colorInt, /* darkTheme= */ true, style)
                 val builder = ColorSeedOption.Builder()
                 builder
                     .setLightColors(lightColorScheme.getLightColorPreview())
@@ -295,12 +318,12 @@
      * order: top left, top right, bottom left, bottom right
      */
     @ColorInt
-    private fun ColorScheme.getRevampedUILightColorPreview(): IntArray {
+    private fun getRevampedUILightColorPreview(colorScheme: ColorScheme): IntArray {
         return intArrayOf(
-            setAlphaComponent(this.accent1.s600, ALPHA_MASK),
-            setAlphaComponent(this.accent1.s600, ALPHA_MASK),
-            setAlphaComponent(this.accent2.s100, ALPHA_MASK),
-            ColorStateList.valueOf(this.accent3.s500).withLStar(59f).colors[0],
+            setAlphaComponent(colorScheme.accent1.s600, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent1.s600, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent2.s100, ALPHA_MASK),
+            ColorStateList.valueOf(colorScheme.accent3.s500).withLStar(59f).colors[0],
         )
     }
 
@@ -309,12 +332,12 @@
      * order: top left, top right, bottom left, bottom right
      */
     @ColorInt
-    private fun ColorScheme.getRevampedUIDarkColorPreview(): IntArray {
+    private fun getRevampedUIDarkColorPreview(colorScheme: ColorScheme): IntArray {
         return intArrayOf(
-            setAlphaComponent(this.accent1.s200, ALPHA_MASK),
-            setAlphaComponent(this.accent1.s200, ALPHA_MASK),
-            setAlphaComponent(this.accent2.s700, ALPHA_MASK),
-            setAlphaComponent(this.accent3.s100, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent1.s200, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent1.s200, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent2.s700, ALPHA_MASK),
+            setAlphaComponent(colorScheme.accent3.s100, ALPHA_MASK),
         )
     }
 
@@ -322,12 +345,12 @@
      * Returns the Revamped UI preview of a preset ColorScheme based on this order: top left, top
      * right, bottom left, bottom right
      */
-    private fun ColorScheme.getRevampedUIPresetColorPreview(seed: Int): IntArray {
+    private fun getRevampedUIPresetColorPreview(colorScheme: ColorScheme, seed: Int): IntArray {
         val colors =
-            when (this.style) {
-                Style.FRUIT_SALAD -> intArrayOf(seed, this.accent1.s100)
-                Style.TONAL_SPOT -> intArrayOf(this.accentColor, this.accentColor)
-                else -> intArrayOf(this.accent1.s100, this.accent1.s100)
+            when (colorScheme.style) {
+                Style.FRUIT_SALAD -> intArrayOf(seed, colorScheme.accent1.s100)
+                Style.TONAL_SPOT -> intArrayOf(colorScheme.accentColor, colorScheme.accentColor)
+                else -> intArrayOf(colorScheme.accent1.s100, colorScheme.accent1.s100)
             }
         return intArrayOf(
             colors[0],
@@ -359,26 +382,12 @@
             // Color option index value starts from 1.
             var index = 1
             val maxPresetColors = if (themeStyleEnabled) bundleNames.size else MAX_PRESET_COLORS
-            for (bundleName in bundleNames.take(maxPresetColors)) {
-                if (shouldUseRevampedUi) {
-                    val builder = ColorOptionImpl.Builder()
-                    builder.title = getItemStringFromStub(COLOR_BUNDLE_NAME_PREFIX, bundleName)
-                    builder.index = index
-                    builder.source = ColorOptionsProvider.COLOR_SOURCE_PRESET
-                    builder.type = ColorType.PRESET_COLOR
-                    val colorFromStub =
-                        getItemColorFromStub(COLOR_BUNDLE_MAIN_COLOR_PREFIX, bundleName)
-                    var darkColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ true)
-                    var lightColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ false)
-                    val lightColor = lightColorScheme.accentColor
-                    val darkColor = darkColorScheme.accentColor
-                    var lightColors = intArrayOf(lightColor, lightColor, lightColor, lightColor)
-                    var darkColors = intArrayOf(darkColor, darkColor, darkColor, darkColor)
-                    builder.addOverlayPackage(OVERLAY_CATEGORY_COLOR, toColorString(colorFromStub))
-                    builder.addOverlayPackage(
-                        OVERLAY_CATEGORY_SYSTEM_PALETTE,
-                        toColorString(colorFromStub)
-                    )
+
+            if (shouldUseRevampedUi) {
+                // keep track of whether monochrome is included in preset colors to determine
+                // inclusion in wallpaper colors
+                var hasMonochrome = false
+                for (bundleName in bundleNames.take(maxPresetColors)) {
                     if (themeStyleEnabled) {
                         val styleName =
                             try {
@@ -393,36 +402,26 @@
                             } catch (e: IllegalArgumentException) {
                                 Style.TONAL_SPOT
                             }
-                        builder.style = style
 
-                        lightColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ false, style)
-                        darkColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ true, style)
-
-                        when (style) {
-                            Style.MONOCHROMATIC -> {
-                                if (
-                                    !InjectorProvider.getInjector()
-                                        .getFlags()
-                                        .isMonochromaticThemeEnabled(mContext)
-                                ) {
-                                    continue
-                                }
-                                darkColors = darkColorScheme.getRevampedUIDarkColorPreview()
-                                lightColors = lightColorScheme.getRevampedUILightColorPreview()
+                        if (style == Style.MONOCHROMATIC) {
+                            if (!monochromeEnabled) {
+                                continue
                             }
-                            else -> {
-                                darkColors =
-                                    darkColorScheme.getRevampedUIPresetColorPreview(colorFromStub)
-                                lightColors =
-                                    lightColorScheme.getRevampedUIPresetColorPreview(colorFromStub)
-                            }
+                            hasMonochrome = true
+                            monochromeBundleName = bundleName
                         }
+                        bundles.add(buildRevampedUIPreset(bundleName, index, style))
+                    } else {
+                        bundles.add(buildRevampedUIPreset(bundleName, index, null))
                     }
-                    builder.lightColors = lightColors
-                    builder.darkColors = darkColors
 
-                    bundles.add(builder.build())
-                } else {
+                    index++
+                }
+                if (!hasMonochrome) {
+                    monochromeBundleName = null
+                }
+            } else {
+                for (bundleName in bundleNames.take(maxPresetColors)) {
                     val builder = ColorBundle.Builder()
                     builder.title = getItemStringFromStub(COLOR_BUNDLE_NAME_PREFIX, bundleName)
                     builder.setIndex(index)
@@ -446,12 +445,7 @@
                                 Style.TONAL_SPOT
                             }
 
-                        if (
-                            style == Style.MONOCHROMATIC &&
-                                !InjectorProvider.getInjector()
-                                    .getFlags()
-                                    .isMonochromaticThemeEnabled(mContext)
-                        ) {
+                        if (style == Style.MONOCHROMATIC && !monochromeEnabled) {
                             continue
                         }
 
@@ -470,10 +464,52 @@
                     }
 
                     bundles.add(builder.build(mContext))
+                    index++
                 }
-                index++
             }
 
             colorBundles = bundles
         }
+
+    private fun buildRevampedUIPreset(
+        bundleName: String,
+        index: Int,
+        style: Style? = null,
+        type: ColorType = ColorType.PRESET_COLOR,
+    ): ColorOptionImpl {
+        val builder = ColorOptionImpl.Builder()
+        builder.title = getItemStringFromStub(COLOR_BUNDLE_NAME_PREFIX, bundleName)
+        builder.index = index
+        builder.source = ColorOptionsProvider.COLOR_SOURCE_PRESET
+        builder.type = type
+        val colorFromStub = getItemColorFromStub(COLOR_BUNDLE_MAIN_COLOR_PREFIX, bundleName)
+        var darkColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ true)
+        var lightColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ false)
+        val lightColor = lightColorScheme.accentColor
+        val darkColor = darkColorScheme.accentColor
+        var lightColors = intArrayOf(lightColor, lightColor, lightColor, lightColor)
+        var darkColors = intArrayOf(darkColor, darkColor, darkColor, darkColor)
+        builder.addOverlayPackage(OVERLAY_CATEGORY_COLOR, toColorString(colorFromStub))
+        builder.addOverlayPackage(OVERLAY_CATEGORY_SYSTEM_PALETTE, toColorString(colorFromStub))
+        if (style != null) {
+            builder.style = style
+
+            lightColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ false, style)
+            darkColorScheme = ColorScheme(colorFromStub, /* darkTheme= */ true, style)
+
+            when (style) {
+                Style.MONOCHROMATIC -> {
+                    darkColors = getRevampedUIDarkColorPreview(darkColorScheme)
+                    lightColors = getRevampedUILightColorPreview(lightColorScheme)
+                }
+                else -> {
+                    darkColors = getRevampedUIPresetColorPreview(darkColorScheme, colorFromStub)
+                    lightColors = getRevampedUIPresetColorPreview(lightColorScheme, colorFromStub)
+                }
+            }
+        }
+        builder.lightColors = lightColors
+        builder.darkColors = darkColors
+        return builder.build()
+    }
 }