Merge "Makes Studio and Soong kotlin+mockito behavior the same" into main
diff --git a/src/com/android/customization/model/color/ColorOption.java b/src/com/android/customization/model/color/ColorOption.java
index 5d2e995..3035221 100644
--- a/src/com/android/customization/model/color/ColorOption.java
+++ b/src/com/android/customization/model/color/ColorOption.java
@@ -19,6 +19,7 @@
 import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -27,6 +28,7 @@
 import com.android.customization.model.CustomizationManager;
 import com.android.customization.model.CustomizationOption;
 import com.android.customization.model.color.ColorOptionsProvider.ColorSource;
+import com.android.customization.module.logging.ThemesUserEventLogger;
 import com.android.systemui.monet.Style;
 import com.android.wallpaper.R;
 
@@ -101,6 +103,19 @@
     }
 
     /**
+     * Gets the seed color from the overlay packages for logging.
+     *
+     * @return an int representing the seed color, or NULL_SEED_COLOR
+     */
+    public int getSeedColorForLogging() {
+        String seedColor = mPackagesByCategory.get(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+        if (seedColor == null || seedColor.isEmpty()) {
+            return ThemesUserEventLogger.NULL_SEED_COLOR;
+        }
+        return Color.parseColor(seedColor);
+    }
+
+    /**
      * This is similar to #equals() but it only compares this theme's packages with the other, that
      * is, it will return true if applying this theme has the same effect of applying the given one.
      */
@@ -209,6 +224,12 @@
     public abstract String getSource();
 
     /**
+     * @return the source of this color option for logging
+     */
+    @ThemesUserEventLogger.ColorSource
+    public abstract int getSourceForLogging();
+
+    /**
      * @return the style of this color option
      */
     public Style getStyle() {
diff --git a/src/com/android/customization/model/color/ColorOptionImpl.kt b/src/com/android/customization/model/color/ColorOptionImpl.kt
index 3273ce2..461d2a3 100644
--- a/src/com/android/customization/model/color/ColorOptionImpl.kt
+++ b/src/com/android/customization/model/color/ColorOptionImpl.kt
@@ -17,6 +17,7 @@
 package com.android.customization.model.color
 
 import android.content.Context
+import android.stats.style.StyleEnums
 import android.view.View
 import androidx.annotation.ColorInt
 import com.android.customization.model.color.ColorOptionsProvider.ColorSource
@@ -68,6 +69,15 @@
         return source
     }
 
+    override fun getSourceForLogging(): Int {
+        return when (getSource()) {
+            ColorOptionsProvider.COLOR_SOURCE_PRESET -> StyleEnums.COLOR_SOURCE_PRESET_COLOR
+            ColorOptionsProvider.COLOR_SOURCE_HOME -> StyleEnums.COLOR_SOURCE_HOME_SCREEN_WALLPAPER
+            ColorOptionsProvider.COLOR_SOURCE_LOCK -> StyleEnums.COLOR_SOURCE_LOCK_SCREEN_WALLPAPER
+            else -> StyleEnums.COLOR_SOURCE_UNSPECIFIED
+        }
+    }
+
     class Builder {
         var title: String? = null
 
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index d2781c2..4b2c899 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -423,6 +423,7 @@
             ?: ColorPickerViewModel.Factory(
                     context.applicationContext,
                     getColorPickerInteractor(context, wallpaperColorsRepository),
+                    userEventLogger,
                 )
                 .also { colorPickerViewModelFactory = it }
     }
diff --git a/src/com/android/customization/picker/color/data/repository/FakeColorPickerRepository.kt b/src/com/android/customization/picker/color/data/repository/FakeColorPickerRepository.kt
index bb2ef9d..f35d934 100644
--- a/src/com/android/customization/picker/color/data/repository/FakeColorPickerRepository.kt
+++ b/src/com/android/customization/picker/color/data/repository/FakeColorPickerRepository.kt
@@ -19,10 +19,12 @@
 import android.content.Context
 import android.graphics.Color
 import android.text.TextUtils
+import com.android.customization.model.ResourceConstants
 import com.android.customization.model.color.ColorOptionImpl
 import com.android.customization.model.color.ColorOptionsProvider
 import com.android.customization.picker.color.shared.model.ColorOptionModel
 import com.android.customization.picker.color.shared.model.ColorType
+import com.android.systemui.monet.Style
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -49,6 +51,53 @@
     }
 
     fun setOptions(
+        wallpaperOptions: List<ColorOptionImpl>,
+        presetOptions: List<ColorOptionImpl>,
+        selectedColorOptionType: ColorType,
+        selectedColorOptionIndex: Int
+    ) {
+        _colorOptions.value =
+            mapOf(
+                ColorType.WALLPAPER_COLOR to
+                    buildList {
+                        for ((index, colorOption) in wallpaperOptions.withIndex()) {
+                            val isSelected =
+                                selectedColorOptionType == ColorType.WALLPAPER_COLOR &&
+                                    selectedColorOptionIndex == index
+                            val colorOptionModel =
+                                ColorOptionModel(
+                                    key = "${ColorType.WALLPAPER_COLOR}::$index",
+                                    colorOption = colorOption,
+                                    isSelected = isSelected
+                                )
+                            if (isSelected) {
+                                selectedColorOption = colorOptionModel
+                            }
+                            add(colorOptionModel)
+                        }
+                    },
+                ColorType.PRESET_COLOR to
+                    buildList {
+                        for ((index, colorOption) in presetOptions.withIndex()) {
+                            val isSelected =
+                                selectedColorOptionType == ColorType.PRESET_COLOR &&
+                                    selectedColorOptionIndex == index
+                            val colorOptionModel =
+                                ColorOptionModel(
+                                    key = "${ColorType.PRESET_COLOR}::$index",
+                                    colorOption = colorOption,
+                                    isSelected = isSelected
+                                )
+                            if (isSelected) {
+                                selectedColorOption = colorOptionModel
+                            }
+                            add(colorOptionModel)
+                        }
+                    },
+            )
+    }
+
+    fun setOptions(
         numWallpaperOptions: Int,
         numPresetOptions: Int,
         selectedColorOptionType: ColorType,
@@ -111,6 +160,22 @@
         return builder.build()
     }
 
+    fun buildPresetOption(style: Style, seedColor: String): ColorOptionImpl {
+        val builder = ColorOptionImpl.Builder()
+        builder.lightColors =
+            intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
+        builder.darkColors =
+            intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
+        builder.type = ColorType.PRESET_COLOR
+        builder.source = ColorOptionsProvider.COLOR_SOURCE_PRESET
+        builder.style = style
+        builder.title = "Preset"
+        builder
+            .addOverlayPackage("TEST_PACKAGE_TYPE", "preset_color")
+            .addOverlayPackage(ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE, seedColor)
+        return builder.build()
+    }
+
     private fun buildWallpaperOption(index: Int): ColorOptionImpl {
         val builder = ColorOptionImpl.Builder()
         builder.lightColors =
@@ -127,6 +192,22 @@
         return builder.build()
     }
 
+    fun buildWallpaperOption(source: String, style: Style, seedColor: String): ColorOptionImpl {
+        val builder = ColorOptionImpl.Builder()
+        builder.lightColors =
+            intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
+        builder.darkColors =
+            intArrayOf(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT)
+        builder.type = ColorType.WALLPAPER_COLOR
+        builder.source = source
+        builder.style = style
+        builder.title = "Dynamic"
+        builder
+            .addOverlayPackage("TEST_PACKAGE_TYPE", "wallpaper_color")
+            .addOverlayPackage(ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE, seedColor)
+        return builder.build()
+    }
+
     override suspend fun select(colorOptionModel: ColorOptionModel) {
         val colorOptions = _colorOptions.value
         val wallpaperColorOptions = colorOptions[ColorType.WALLPAPER_COLOR]!!
diff --git a/src/com/android/customization/picker/color/ui/viewmodel/ColorPickerViewModel.kt b/src/com/android/customization/picker/color/ui/viewmodel/ColorPickerViewModel.kt
index 67c6838..3c3d114 100644
--- a/src/com/android/customization/picker/color/ui/viewmodel/ColorPickerViewModel.kt
+++ b/src/com/android/customization/picker/color/ui/viewmodel/ColorPickerViewModel.kt
@@ -21,6 +21,7 @@
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
 import com.android.customization.model.color.ColorOptionImpl
+import com.android.customization.module.logging.ThemesUserEventLogger
 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
 import com.android.customization.picker.color.shared.model.ColorType
 import com.android.wallpaper.R
@@ -43,6 +44,7 @@
 private constructor(
     context: Context,
     private val interactor: ColorPickerInteractor,
+    private val logger: ThemesUserEventLogger,
 ) : ViewModel() {
 
     private val selectedColorTypeTabId = MutableStateFlow<ColorType?>(null)
@@ -142,6 +144,14 @@
                                                 {
                                                     viewModelScope.launch {
                                                         interactor.select(colorOptionModel)
+                                                        logger.logThemeColorApplied(
+                                                            colorOptionModel.colorOption
+                                                                .sourceForLogging,
+                                                            colorOptionModel.colorOption.style
+                                                                .ordinal + 1,
+                                                            colorOptionModel.colorOption
+                                                                .seedColorForLogging,
+                                                        )
                                                     }
                                                 }
                                             }
@@ -205,12 +215,14 @@
     class Factory(
         private val context: Context,
         private val interactor: ColorPickerInteractor,
+        private val logger: ThemesUserEventLogger,
     ) : ViewModelProvider.Factory {
         override fun <T : ViewModel> create(modelClass: Class<T>): T {
             @Suppress("UNCHECKED_CAST")
             return ColorPickerViewModel(
                 context = context,
                 interactor = interactor,
+                logger = logger,
             )
                 as T
         }
diff --git a/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
index 10149f0..bb49ff0 100644
--- a/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
+++ b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
@@ -28,8 +28,19 @@
 class TestThemesUserEventLogger @Inject constructor() :
     TestUserEventLogger(), ThemesUserEventLogger {
     @ClockSize private var clockSize: Int = StyleEnums.CLOCK_SIZE_UNSPECIFIED
+    @ColorSource
+    var themeColorSource: Int = StyleEnums.COLOR_SOURCE_UNSPECIFIED
+        private set
+    var themeColorVariant: Int = -1
+        private set
+    var themeSeedColor: Int = -1
+        private set
 
-    override fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int) {}
+    override fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int) {
+        this.themeColorSource = source
+        this.themeColorVariant = variant
+        this.themeSeedColor = seedColor
+    }
 
     override fun logGridApplied(grid: GridOption) {}
 
diff --git a/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt b/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
index 9968c5f..c841267 100644
--- a/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/color/ui/viewmodel/ColorPickerViewModelTest.kt
@@ -17,8 +17,12 @@
 package com.android.customization.model.picker.color.ui.viewmodel
 
 import android.content.Context
+import android.graphics.Color
+import android.stats.style.StyleEnums
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.model.color.ColorOptionsProvider
+import com.android.customization.module.logging.TestThemesUserEventLogger
 import com.android.customization.picker.color.data.repository.FakeColorPickerRepository
 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
 import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
@@ -26,6 +30,7 @@
 import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel
 import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
 import com.android.customization.picker.color.ui.viewmodel.ColorTypeTabViewModel
+import com.android.systemui.monet.Style
 import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
 import com.android.wallpaper.testing.FakeSnapshotStore
 import com.android.wallpaper.testing.collectLastValue
@@ -36,6 +41,7 @@
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
 import kotlinx.coroutines.test.resetMain
 import kotlinx.coroutines.test.runTest
 import kotlinx.coroutines.test.setMain
@@ -49,6 +55,7 @@
 @SmallTest
 @RunWith(RobolectricTestRunner::class)
 class ColorPickerViewModelTest {
+    private val logger = TestThemesUserEventLogger()
     private lateinit var underTest: ColorPickerViewModel
     private lateinit var repository: FakeColorPickerRepository
     private lateinit var interactor: ColorPickerInteractor
@@ -77,7 +84,11 @@
             )
 
         underTest =
-            ColorPickerViewModel.Factory(context = context, interactor = interactor)
+            ColorPickerViewModel.Factory(
+                    context = context,
+                    interactor = interactor,
+                    logger = logger
+                )
                 .create(ColorPickerViewModel::class.java)
 
         repository.setOptions(4, 4, ColorType.WALLPAPER_COLOR, 0)
@@ -112,6 +123,67 @@
         }
 
     @Test
+    fun `Log selected wallpaper color`() =
+        testScope.runTest {
+            repository.setOptions(
+                listOf(
+                    repository.buildWallpaperOption(
+                        ColorOptionsProvider.COLOR_SOURCE_LOCK,
+                        Style.EXPRESSIVE,
+                        "#121212"
+                    )
+                ),
+                listOf(repository.buildPresetOption(Style.FRUIT_SALAD, "#ABCDEF")),
+                ColorType.PRESET_COLOR,
+                0
+            )
+
+            val colorTypes = collectLastValue(underTest.colorTypeTabs)
+            val colorOptions = collectLastValue(underTest.colorOptions)
+
+            // Select "Wallpaper colors" tab
+            colorTypes()?.get(ColorType.WALLPAPER_COLOR)?.onClick?.invoke()
+            // Select a color option
+            selectColorOption(colorOptions, 0)
+            advanceUntilIdle()
+
+            assertThat(logger.themeColorSource)
+                .isEqualTo(StyleEnums.COLOR_SOURCE_LOCK_SCREEN_WALLPAPER)
+            assertThat(logger.themeColorVariant).isEqualTo(Style.EXPRESSIVE.ordinal + 1)
+            assertThat(logger.themeSeedColor).isEqualTo(Color.parseColor("#121212"))
+        }
+
+    @Test
+    fun `Log selected preset color`() =
+        testScope.runTest {
+            repository.setOptions(
+                listOf(
+                    repository.buildWallpaperOption(
+                        ColorOptionsProvider.COLOR_SOURCE_LOCK,
+                        Style.EXPRESSIVE,
+                        "#121212"
+                    )
+                ),
+                listOf(repository.buildPresetOption(Style.FRUIT_SALAD, "#ABCDEF")),
+                ColorType.WALLPAPER_COLOR,
+                0
+            )
+
+            val colorTypes = collectLastValue(underTest.colorTypeTabs)
+            val colorOptions = collectLastValue(underTest.colorOptions)
+
+            // Select "Wallpaper colors" tab
+            colorTypes()?.get(ColorType.PRESET_COLOR)?.onClick?.invoke()
+            // Select a color option
+            selectColorOption(colorOptions, 0)
+            advanceUntilIdle()
+
+            assertThat(logger.themeColorSource).isEqualTo(StyleEnums.COLOR_SOURCE_PRESET_COLOR)
+            assertThat(logger.themeColorVariant).isEqualTo(Style.FRUIT_SALAD.ordinal + 1)
+            assertThat(logger.themeSeedColor).isEqualTo(Color.parseColor("#ABCDEF"))
+        }
+
+    @Test
     fun `Select a preset color`() =
         testScope.runTest {
             val colorTypes = collectLastValue(underTest.colorTypeTabs)