Merge "Adjust quick affordance section controller to use base flags (2/3)" into main
diff --git a/res/layout/clock_size_radio_button_group.xml b/res/layout/clock_size_radio_button_group.xml
index 5e8fcf5..4e7d1b4 100644
--- a/res/layout/clock_size_radio_button_group.xml
+++ b/res/layout/clock_size_radio_button_group.xml
@@ -32,7 +32,8 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
             android:layout_marginEnd="8dp"
-            android:clickable="false" />
+            android:clickable="false"
+            android:importantForAccessibility="no"/>
 
         <LinearLayout
             android:layout_width="match_parent"
@@ -71,7 +72,8 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
             android:layout_marginEnd="8dp"
-            android:clickable="false" />
+            android:clickable="false"
+            android:importantForAccessibility="no"/>
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 9b13119..4bb2b72 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -23,7 +23,6 @@
 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
 import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
@@ -58,6 +57,8 @@
 
     fun getClockCarouselViewModelFactory(
         interactor: ClockPickerInteractor,
+        clockViewFactory: ClockViewFactory,
+        resources: Resources,
     ): ClockCarouselViewModel.Factory
 
     fun getClockViewFactory(activity: ComponentActivity): ClockViewFactory
@@ -67,6 +68,4 @@
         wallpaperColorsRepository: WallpaperColorsRepository,
         clockViewFactory: ClockViewFactory,
     ): ClockSettingsViewModel.Factory
-
-    fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils
 }
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index eb0b601..10bbd7a 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -36,8 +36,8 @@
 import com.android.customization.model.themedicon.data.repository.ThemeIconRepository
 import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor
 import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer
-import com.android.customization.module.logging.StatsLogUserEventLogger
 import com.android.customization.module.logging.ThemesUserEventLogger
+import com.android.customization.module.logging.ThemesUserEventLoggerImpl
 import com.android.customization.picker.clock.data.repository.ClockPickerRepositoryImpl
 import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
@@ -47,8 +47,6 @@
 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
-import com.android.customization.picker.clock.utils.ThemePickerClockDescriptionUtils
 import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
 import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
@@ -123,7 +121,6 @@
     private var themedIconSnapshotRestorer: ThemedIconSnapshotRestorer? = null
     private var themedIconInteractor: ThemedIconInteractor? = null
     private var clockSettingsViewModelFactory: ClockSettingsViewModel.Factory? = null
-    private var clockDescriptionUtils: ClockDescriptionUtils? = null
     private var gridInteractor: GridInteractor? = null
     private var gridSnapshotRestorer: GridSnapshotRestorer? = null
     private var gridScreenViewModelFactory: GridScreenViewModel.Factory? = null
@@ -143,6 +140,8 @@
                     getFlags(),
                     getClockCarouselViewModelFactory(
                         getClockPickerInteractor(activity.applicationContext),
+                        getClockViewFactory(activity),
+                        resources = activity.resources,
                     ),
                     getClockViewFactory(activity),
                     getDarkModeSnapshotRestorer(activity),
@@ -168,7 +167,7 @@
     @Synchronized
     override fun getUserEventLogger(context: Context): ThemesUserEventLogger {
         return userEventLogger as? ThemesUserEventLogger
-            ?: StatsLogUserEventLogger(getPreferences(context.applicationContext)).also {
+            ?: ThemesUserEventLoggerImpl(getPreferences(context.applicationContext)).also {
                 userEventLogger = it
             }
     }
@@ -363,11 +362,12 @@
 
     override fun getClockCarouselViewModelFactory(
         interactor: ClockPickerInteractor,
+        clockViewFactory: ClockViewFactory,
+        resources: Resources,
     ): ClockCarouselViewModel.Factory {
         return clockCarouselViewModelFactory
-            ?: ClockCarouselViewModel.Factory(interactor, bgDispatcher).also {
-                clockCarouselViewModelFactory = it
-            }
+            ?: ClockCarouselViewModel.Factory(interactor, bgDispatcher, clockViewFactory, resources)
+                .also { clockCarouselViewModelFactory = it }
     }
 
     override fun getClockViewFactory(activity: ComponentActivity): ClockViewFactory {
@@ -508,11 +508,6 @@
                 .also { clockSettingsViewModelFactory = it }
     }
 
-    override fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils {
-        return clockDescriptionUtils
-            ?: ThemePickerClockDescriptionUtils().also { clockDescriptionUtils = it }
-    }
-
     fun getGridScreenViewModelFactory(
         context: Context,
     ): ViewModelProvider.Factory {
diff --git a/src/com/android/customization/module/SysUiStatsLogger.kt b/src/com/android/customization/module/logging/SysUiStatsLogger.kt
similarity index 80%
rename from src/com/android/customization/module/SysUiStatsLogger.kt
rename to src/com/android/customization/module/logging/SysUiStatsLogger.kt
index 142bd22..14f0be6 100644
--- a/src/com/android/customization/module/SysUiStatsLogger.kt
+++ b/src/com/android/customization/module/logging/SysUiStatsLogger.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.customization.module
+package com.android.customization.module.logging
 
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.shared.system.SysUiStatsLog.STYLE_UICHANGED__CLOCK_SIZE__CLOCK_SIZE_UNSPECIFIED
@@ -38,9 +38,11 @@
     private var wallpaperCategoryHash = 0
     private var wallpaperIdHash = 0
     private var colorPreference = 0
-    private var locationPreference = STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_PREFERENCE_UNSPECIFIED
+    private var locationPreference =
+        STYLE_UICHANGED__LOCATION_PREFERENCE__LOCATION_PREFERENCE_UNSPECIFIED
     private var datePreference = STYLE_UICHANGED__DATE_PREFERENCE__DATE_PREFERENCE_UNSPECIFIED
-    private var launchedPreference = STYLE_UICHANGED__LAUNCHED_PREFERENCE__LAUNCHED_PREFERENCE_UNSPECIFIED
+    private var launchedPreference =
+        STYLE_UICHANGED__LAUNCHED_PREFERENCE__LAUNCHED_PREFERENCE_UNSPECIFIED
     private var effectPreference = STYLE_UICHANGED__EFFECT_PREFERENCE__EFFECT_PREFERENCE_UNSPECIFIED
     private var effectIdHash = 0
     private var lockWallpaperCategoryHash = 0
@@ -52,8 +54,10 @@
     private var timeElapsedMillis = 0L
     private var effectResultCode = -1
     private var sessionId = 0
-    private var setWallpaperEntryPoint = STYLE_UICHANGED__SET_WALLPAPER_ENTRY_POINT__SET_WALLPAPER_ENTRY_POINT_UNSPECIFIED
-    private var wallpaperDestination = STYLE_UICHANGED__WALLPAPER_DESTINATION__WALLPAPER_DESTINATION_UNSPECIFIED
+    private var setWallpaperEntryPoint =
+        STYLE_UICHANGED__SET_WALLPAPER_ENTRY_POINT__SET_WALLPAPER_ENTRY_POINT_UNSPECIFIED
+    private var wallpaperDestination =
+        STYLE_UICHANGED__WALLPAPER_DESTINATION__WALLPAPER_DESTINATION_UNSPECIFIED
     private var colorSource = STYLE_UICHANGED__COLOR_SOURCE__COLOR_SOURCE_UNSPECIFIED
     private var seedColor = 0
     private var clockSize = STYLE_UICHANGED__CLOCK_SIZE__CLOCK_SIZE_UNSPECIFIED
@@ -65,9 +69,7 @@
         this.colorPackageHash = colorPackageHash
     }
 
-    fun setFontPackageHash(fontPackageHash: Int) = apply {
-        this.fontPackageHash = fontPackageHash
-    }
+    fun setFontPackageHash(fontPackageHash: Int) = apply { this.fontPackageHash = fontPackageHash }
 
     fun setShapePackageHash(shapePackageHash: Int) = apply {
         this.shapePackageHash = shapePackageHash
@@ -83,13 +85,9 @@
         this.wallpaperCategoryHash = wallpaperCategoryHash
     }
 
-    fun setWallpaperIdHash(wallpaperIdHash: Int) = apply {
-        this.wallpaperIdHash = wallpaperIdHash
-    }
+    fun setWallpaperIdHash(wallpaperIdHash: Int) = apply { this.wallpaperIdHash = wallpaperIdHash }
 
-    fun setColorPreference(colorPreference: Int) = apply {
-        this.colorPreference = colorPreference
-    }
+    fun setColorPreference(colorPreference: Int) = apply { this.colorPreference = colorPreference }
 
     fun setLocationPreference(locationPreference: Int) = apply {
         this.locationPreference = locationPreference
@@ -128,16 +126,14 @@
     fun setColorVariant(colorVariant: Int) = apply { this.colorVariant = colorVariant }
 
     fun setTimeElapsed(timeElapsedMillis: Long) = apply {
-      this.timeElapsedMillis = timeElapsedMillis
+        this.timeElapsedMillis = timeElapsedMillis
     }
 
     fun setEffectResultCode(effectResultCode: Int) = apply {
         this.effectResultCode = effectResultCode
     }
 
-    fun setSessionId(sessionId: Int) = apply {
-        this.sessionId = sessionId
-    }
+    fun setSessionId(sessionId: Int) = apply { this.sessionId = sessionId }
 
     fun setSetWallpaperEntryPoint(@SetWallpaperEntryPoint setWallpaperEntryPoint: Int) = apply {
         this.setWallpaperEntryPoint = setWallpaperEntryPoint
@@ -147,29 +143,17 @@
         this.wallpaperDestination = wallpaperDestination
     }
 
-    fun setColorSource(colorSource: Int) = apply {
-        this.colorSource = colorSource
-    }
+    fun setColorSource(colorSource: Int) = apply { this.colorSource = colorSource }
 
-    fun setSeedColor(seedColor: Int) = apply {
-        this.seedColor = seedColor
-    }
+    fun setSeedColor(seedColor: Int) = apply { this.seedColor = seedColor }
 
-    fun setClockSize(clockSize: Int) = apply {
-        this.clockSize = clockSize
-    }
+    fun setClockSize(clockSize: Int) = apply { this.clockSize = clockSize }
 
-    fun setToggleOn(toggleOn: Boolean) = apply {
-        this.toggleOn = toggleOn
-    }
+    fun setToggleOn(toggleOn: Boolean) = apply { this.toggleOn = toggleOn }
 
-    fun setShortcut(shortcut: String) = apply {
-        this.shortcut = shortcut
-    }
+    fun setShortcut(shortcut: String) = apply { this.shortcut = shortcut }
 
-    fun setShortcutSlotId(shortcutSlotId: String) = apply {
-        this.shortcutSlotId = shortcutSlotId
-    }
+    fun setShortcutSlotId(shortcutSlotId: String) = apply { this.shortcutSlotId = shortcutSlotId }
 
     fun log() {
         SysUiStatsLog.write(
diff --git a/src/com/android/customization/module/logging/ThemesUserEventLogger.kt b/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
index 1210343..087bef4 100644
--- a/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
+++ b/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
@@ -17,14 +17,13 @@
 
 import android.stats.style.StyleEnums
 import androidx.annotation.IntDef
-import com.android.customization.model.color.ColorOption
 import com.android.customization.model.grid.GridOption
 import com.android.wallpaper.module.logging.UserEventLogger
 
 /** Extension of [UserEventLogger] that adds ThemePicker specific events. */
 interface ThemesUserEventLogger : UserEventLogger {
 
-    fun logThemeColorApplied(colorOption: ColorOption)
+    fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int)
 
     fun logGridApplied(grid: GridOption)
 
@@ -43,6 +42,15 @@
     fun logDarkThemeApplied(useDarkTheme: Boolean)
 
     @IntDef(
+        StyleEnums.COLOR_SOURCE_UNSPECIFIED,
+        StyleEnums.COLOR_SOURCE_HOME_SCREEN_WALLPAPER,
+        StyleEnums.COLOR_SOURCE_LOCK_SCREEN_WALLPAPER,
+        StyleEnums.COLOR_SOURCE_PRESET_COLOR,
+    )
+    @Retention(AnnotationRetention.SOURCE)
+    annotation class ColorSource
+
+    @IntDef(
         StyleEnums.CLOCK_SIZE_UNSPECIFIED,
         StyleEnums.CLOCK_SIZE_DYNAMIC,
         StyleEnums.CLOCK_SIZE_SMALL,
diff --git a/src/com/android/customization/module/logging/StatsLogUserEventLogger.kt b/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
similarity index 94%
rename from src/com/android/customization/module/logging/StatsLogUserEventLogger.kt
rename to src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
index 344a4f8..78b5ca7 100644
--- a/src/com/android/customization/module/logging/StatsLogUserEventLogger.kt
+++ b/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
@@ -19,24 +19,22 @@
 import android.content.Intent
 import android.stats.style.StyleEnums
 import android.text.TextUtils
-import com.android.customization.model.color.ColorOption
 import com.android.customization.model.grid.GridOption
-import com.android.customization.module.SysUiStatsLogger
 import com.android.customization.module.logging.ThemesUserEventLogger.ClockSize
+import com.android.customization.module.logging.ThemesUserEventLogger.ColorSource
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.wallpaper.module.WallpaperPersister.DEST_BOTH
 import com.android.wallpaper.module.WallpaperPersister.DEST_HOME_SCREEN
 import com.android.wallpaper.module.WallpaperPersister.DEST_LOCK_SCREEN
 import com.android.wallpaper.module.WallpaperPreferences
-import com.android.wallpaper.module.logging.NoOpUserEventLogger
 import com.android.wallpaper.module.logging.UserEventLogger.EffectStatus
 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
 import com.android.wallpaper.module.logging.UserEventLogger.WallpaperDestination
 import com.android.wallpaper.util.LaunchSourceUtils
 
 /** StatsLog-backed implementation of [ThemesUserEventLogger]. */
-class StatsLogUserEventLogger(private val preferences: WallpaperPreferences) :
-    NoOpUserEventLogger(), ThemesUserEventLogger {
+class ThemesUserEventLoggerImpl(private val preferences: WallpaperPreferences) :
+    ThemesUserEventLogger {
 
     override fun logSnapshot() {
         SysUiStatsLogger(StyleEnums.SNAPSHOT)
@@ -117,10 +115,15 @@
         SysUiStatsLogger(StyleEnums.WALLPAPER_EXPLORE).log()
     }
 
-    override fun logThemeColorApplied(colorOption: ColorOption) {
+    override fun logThemeColorApplied(
+        @ColorSource source: Int,
+        variant: Int,
+        seedColor: Int,
+    ) {
         SysUiStatsLogger(StyleEnums.THEME_COLOR_APPLIED)
-            .setColorPreference(colorOption.index)
-            .setColorVariant(colorOption.style.ordinal + 1)
+            .setColorSource(source)
+            .setColorVariant(variant)
+            .setSeedColor(seedColor)
             .log()
     }
 
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
index 004103f..8923b46 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -187,7 +187,6 @@
     ): ClockMetadataModel {
         return ClockMetadataModel(
             clockId = clockId,
-            name = name,
             isSelected = isSelected,
             selectedColorId = selectedColorId,
             colorToneProgress = colorTone,
diff --git a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
index 2522507..6e2bfb3 100644
--- a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
+++ b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
@@ -23,7 +23,6 @@
 /** Model for clock metadata. */
 data class ClockMetadataModel(
     val clockId: String,
-    val name: String,
     val isSelected: Boolean,
     val selectedColorId: String?,
     @IntRange(from = 0, to = 100) val colorToneProgress: Int,
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
index 068f44f..dc70633 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -88,14 +88,14 @@
                             injector
                                 .getCurrentWallpaperInfoFactory(context)
                                 .createCurrentWallpaperInfos(
-                                    { homeWallpaper, lockWallpaper, _ ->
-                                        continuation.resume(
-                                            lockWallpaper ?: homeWallpaper,
-                                            null,
-                                        )
-                                    },
+                                    context,
                                     forceReload,
-                                )
+                                ) { homeWallpaper, lockWallpaper, _ ->
+                                    continuation.resume(
+                                        lockWallpaper ?: homeWallpaper,
+                                        null,
+                                    )
+                                }
                         }
                     },
                     onWallpaperColorChanged = { colors ->
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index d4f501b..fbc8a96 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -384,7 +384,7 @@
     ) : Carousel.Adapter {
 
         fun getContentDescription(index: Int, resources: Resources): String {
-            return clocks[index].getContentDescription(resources)
+            return clocks[index].contentDescription
         }
 
         override fun count(): Int {
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
index 9811426..e5ac953 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
@@ -15,20 +15,8 @@
  */
 package com.android.customization.picker.clock.ui.viewmodel
 
-import android.content.res.Resources
-import com.android.customization.module.CustomizationInjector
-import com.android.wallpaper.R
-import com.android.wallpaper.module.InjectorProvider
-
-class ClockCarouselItemViewModel(val clockId: String, val isSelected: Boolean) {
-
-    /** Description for accessibility purposes when a clock is selected. */
-    fun getContentDescription(resources: Resources): String {
-        val clockContent =
-            (InjectorProvider.getInjector() as? CustomizationInjector)
-                ?.getClockDescriptionUtils(resources)
-                ?.getDescription(clockId)
-                ?: ""
-        return resources.getString(R.string.select_clock_action_description, clockContent)
-    }
-}
+class ClockCarouselItemViewModel(
+    val clockId: String,
+    val isSelected: Boolean,
+    val contentDescription: String,
+)
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
index 27c25a2..e4d5a8d 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -15,12 +15,14 @@
  */
 package com.android.customization.picker.clock.ui.viewmodel
 
+import android.content.res.Resources
 import android.graphics.Color
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
 import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.wallpaper.R
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -43,6 +45,8 @@
 class ClockCarouselViewModel(
     private val interactor: ClockPickerInteractor,
     private val backgroundDispatcher: CoroutineDispatcher,
+    private val clockViewFactory: ClockViewFactory,
+    private val resources: Resources,
 ) : ViewModel() {
     @OptIn(ExperimentalCoroutinesApi::class)
     val allClocks: StateFlow<List<ClockCarouselItemViewModel>> =
@@ -50,7 +54,14 @@
             .mapLatest { allClocks ->
                 // Delay to avoid the case that the full list of clocks is not initiated.
                 delay(CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
-                allClocks.map { ClockCarouselItemViewModel(it.clockId, it.isSelected) }
+                allClocks.map {
+                    val contentDescription =
+                        resources.getString(
+                            R.string.select_clock_action_description,
+                            clockViewFactory.getController(it.clockId).config.description
+                        )
+                    ClockCarouselItemViewModel(it.clockId, it.isSelected, contentDescription)
+                }
             }
             .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
 
@@ -117,12 +128,16 @@
     class Factory(
         private val interactor: ClockPickerInteractor,
         private val backgroundDispatcher: CoroutineDispatcher,
+        private val clockViewFactory: ClockViewFactory,
+        private val resources: Resources,
     ) : ViewModelProvider.Factory {
         override fun <T : ViewModel> create(modelClass: Class<T>): T {
             @Suppress("UNCHECKED_CAST")
             return ClockCarouselViewModel(
                 interactor = interactor,
                 backgroundDispatcher = backgroundDispatcher,
+                clockViewFactory = clockViewFactory,
+                resources = resources,
             )
                 as T
         }
diff --git a/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt b/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt
deleted file mode 100644
index 28ea4a3..0000000
--- a/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2023 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.customization.picker.clock.utils
-
-/** Provides clock description for accessibility purposes. */
-interface ClockDescriptionUtils {
-
-    /**
-     * TODO (b/287507746) : Migrate the clock description to system UI or a shared library, instead
-     * of preserving at the Wallpaper Picker side.
-     */
-    fun getDescription(clockId: String): String
-}
diff --git a/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt b/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt
deleted file mode 100644
index a04ebff..0000000
--- a/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2023 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.customization.picker.clock.utils
-
-class ThemePickerClockDescriptionUtils : ClockDescriptionUtils {
-    override fun getDescription(clockId: String): String {
-        return ""
-    }
-}
diff --git a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
index 911b821..941d2c6 100644
--- a/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
+++ b/src/com/android/customization/picker/color/ui/fragment/ColorPickerFragment.kt
@@ -114,23 +114,23 @@
                         wallpaperInfoProvider = { forceReload ->
                             suspendCancellableCoroutine { continuation ->
                                 wallpaperInfoFactory.createCurrentWallpaperInfos(
-                                    { homeWallpaper, lockWallpaper, _ ->
-                                        lifecycleScope.launch {
-                                            if (
-                                                wallpaperColorsRepository.lockWallpaperColors.value
-                                                    is WallpaperColorsModel.Loading
-                                            ) {
-                                                loadInitialColors(
-                                                    wallpaperManager,
-                                                    wallpaperColorsRepository,
-                                                    CustomizationSections.Screen.LOCK_SCREEN
-                                                )
-                                            }
-                                        }
-                                        continuation.resume(lockWallpaper ?: homeWallpaper, null)
-                                    },
+                                    context,
                                     forceReload,
-                                )
+                                ) { homeWallpaper, lockWallpaper, _ ->
+                                    lifecycleScope.launch {
+                                        if (
+                                            wallpaperColorsRepository.lockWallpaperColors.value
+                                                is WallpaperColorsModel.Loading
+                                        ) {
+                                            loadInitialColors(
+                                                wallpaperManager,
+                                                wallpaperColorsRepository,
+                                                CustomizationSections.Screen.LOCK_SCREEN
+                                            )
+                                        }
+                                    }
+                                    continuation.resume(lockWallpaper ?: homeWallpaper, null)
+                                }
                             }
                         },
                         onWallpaperColorChanged = { colors ->
@@ -165,23 +165,23 @@
                     wallpaperInfoProvider = { forceReload ->
                         suspendCancellableCoroutine { continuation ->
                             wallpaperInfoFactory.createCurrentWallpaperInfos(
-                                { homeWallpaper, lockWallpaper, _ ->
-                                    lifecycleScope.launch {
-                                        if (
-                                            wallpaperColorsRepository.homeWallpaperColors.value
-                                                is WallpaperColorsModel.Loading
-                                        ) {
-                                            loadInitialColors(
-                                                wallpaperManager,
-                                                wallpaperColorsRepository,
-                                                CustomizationSections.Screen.HOME_SCREEN
-                                            )
-                                        }
-                                    }
-                                    continuation.resume(homeWallpaper ?: lockWallpaper, null)
-                                },
+                                context,
                                 forceReload,
-                            )
+                            ) { homeWallpaper, lockWallpaper, _ ->
+                                lifecycleScope.launch {
+                                    if (
+                                        wallpaperColorsRepository.homeWallpaperColors.value
+                                            is WallpaperColorsModel.Loading
+                                    ) {
+                                        loadInitialColors(
+                                            wallpaperManager,
+                                            wallpaperColorsRepository,
+                                            CustomizationSections.Screen.HOME_SCREEN
+                                        )
+                                    }
+                                }
+                                continuation.resume(homeWallpaper ?: lockWallpaper, null)
+                            }
                         }
                     },
                     onWallpaperColorChanged = { colors ->
diff --git a/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt b/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
index 52bc5e1..2a301b4 100644
--- a/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
+++ b/src/com/android/customization/picker/grid/ui/fragment/GridFragment.kt
@@ -185,11 +185,11 @@
                     wallpaperInfoProvider = {
                         suspendCancellableCoroutine { continuation ->
                             wallpaperInfoFactory.createCurrentWallpaperInfos(
-                                { homeWallpaper, lockWallpaper, _ ->
-                                    continuation.resume(homeWallpaper ?: lockWallpaper, null)
-                                },
+                                context,
                                 /* forceRefresh= */ true,
-                            )
+                            ) { homeWallpaper, lockWallpaper, _ ->
+                                continuation.resume(homeWallpaper ?: lockWallpaper, null)
+                            }
                         }
                     },
                     wallpaperInteractor = wallpaperInteractor,
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
index 0edc216..b3e778b 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithThemeSectionController.kt
@@ -35,6 +35,7 @@
 import com.android.wallpaper.picker.customization.ui.viewmodel.ScreenPreviewViewModel
 import com.android.wallpaper.util.DisplayUtils
 import com.android.wallpaper.util.PreviewUtils
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.suspendCancellableCoroutine
 
 /**
@@ -69,6 +70,7 @@
         isTwoPaneAndSmallWidth,
         customizationPickerViewModel,
     ) {
+    @OptIn(ExperimentalCoroutinesApi::class)
     override fun createScreenPreviewViewModel(context: Context): ScreenPreviewViewModel {
         return PreviewWithThemeViewModel(
             previewUtils =
@@ -92,21 +94,21 @@
             wallpaperInfoProvider = { forceReload ->
                 suspendCancellableCoroutine { continuation ->
                     wallpaperInfoFactory.createCurrentWallpaperInfos(
-                        { homeWallpaper, lockWallpaper, _ ->
-                            val wallpaper =
-                                if (isOnLockScreen) {
-                                    lockWallpaper ?: homeWallpaper
-                                } else {
-                                    homeWallpaper ?: lockWallpaper
-                                }
-                            loadInitialColors(
-                                context = context,
-                                screen = screen,
-                            )
-                            continuation.resume(wallpaper, null)
-                        },
+                        context,
                         forceReload,
-                    )
+                    ) { homeWallpaper, lockWallpaper, _ ->
+                        val wallpaper =
+                            if (isOnLockScreen) {
+                                lockWallpaper ?: homeWallpaper
+                            } else {
+                                homeWallpaper ?: lockWallpaper
+                            }
+                        loadInitialColors(
+                            context = context,
+                            screen = screen,
+                        )
+                        continuation.resume(wallpaper, null)
+                    }
                 }
             },
             onWallpaperColorChanged = { colors ->
diff --git a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
index f832cde..809d20e 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
@@ -92,11 +92,11 @@
             wallpaperInfoProvider = { forceReload ->
                 suspendCancellableCoroutine { continuation ->
                     wallpaperInfoFactory.createCurrentWallpaperInfos(
-                        { homeWallpaper, lockWallpaper, _ ->
-                            continuation.resume(lockWallpaper ?: homeWallpaper, null)
-                        },
+                        context,
                         forceReload,
-                    )
+                    ) { homeWallpaper, lockWallpaper, _ ->
+                        continuation.resume(lockWallpaper ?: homeWallpaper, null)
+                    }
                 }
             },
             wallpaperInteractor = wallpaperInteractor,
diff --git a/tests/Android.bp b/tests/Android.bp
index 2ab3ebc..74dc6a1 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -59,7 +59,7 @@
         "mockito-target-minus-junit4",
         "junit",
         "kotlinx_coroutines_test",
-        "truth-prebuilt",
+        "truth",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index d488ee4..0961886 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -25,8 +25,8 @@
 
     defaults: ["ThemePicker_common_defaults"],
     srcs: [
-        "src/com/android/customization/testing/**/*.java",
-        "src/com/android/customization/testing/**/*.kt",
+        "src/**/*.java",
+        "src/**/*.kt",
     ],
     static_libs: [
         "WallpaperPicker2TestLib",
diff --git a/tests/common/src/com/android/customization/testing/TestThemesUserEventLogger.kt b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
similarity index 85%
rename from tests/common/src/com/android/customization/testing/TestThemesUserEventLogger.kt
rename to tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
index 8b14688..a8989c5 100644
--- a/tests/common/src/com/android/customization/testing/TestThemesUserEventLogger.kt
+++ b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
@@ -13,17 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.customization.testing
+package com.android.customization.module.logging
 
-import com.android.customization.model.color.ColorOption
 import com.android.customization.model.grid.GridOption
-import com.android.customization.module.logging.ThemesUserEventLogger
-import com.android.wallpaper.testing.TestUserEventLogger
+import com.android.customization.module.logging.ThemesUserEventLogger.ColorSource
+import com.android.wallpaper.module.logging.TestUserEventLogger
 
 /** Test implementation of [ThemesUserEventLogger]. */
 class TestThemesUserEventLogger : TestUserEventLogger(), ThemesUserEventLogger {
 
-    override fun logThemeColorApplied(colorOption: ColorOption) {}
+    override fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int) {}
 
     override fun logGridApplied(grid: GridOption) {}
 
diff --git a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
index 0331f8d..e08209d 100644
--- a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -5,13 +5,13 @@
 import androidx.activity.ComponentActivity
 import com.android.customization.module.CustomizationInjector
 import com.android.customization.module.CustomizationPreferences
+import com.android.customization.module.logging.TestThemesUserEventLogger
 import com.android.customization.module.logging.ThemesUserEventLogger
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
 import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
 import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
 import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
@@ -70,7 +70,9 @@
     }
 
     override fun getClockCarouselViewModelFactory(
-        interactor: ClockPickerInteractor
+        interactor: ClockPickerInteractor,
+        clockViewFactory: ClockViewFactory,
+        resources: Resources,
     ): ClockCarouselViewModel.Factory {
         throw UnsupportedOperationException("not implemented")
     }
@@ -87,10 +89,6 @@
         throw UnsupportedOperationException("not implemented")
     }
 
-    override fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils {
-        throw UnsupportedOperationException("not implemented")
-    }
-
     /////////////////
     // TestInjector overrides
     /////////////////
diff --git a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 95d7e35..4d8f32e 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -46,7 +46,6 @@
             checkNotNull(selectedClock)
             ClockMetadataModel(
                 clockId = selectedClock.clockId,
-                name = selectedClock.name,
                 isSelected = true,
                 selectedColorId = selectedColor,
                 colorToneProgress = colorTone,
@@ -82,10 +81,10 @@
         const val CLOCK_ID_3 = "clock3"
         val fakeClocks =
             listOf(
-                ClockMetadataModel(CLOCK_ID_0, "clock0", true, null, 50, null),
-                ClockMetadataModel(CLOCK_ID_1, "clock1", false, null, 50, null),
-                ClockMetadataModel(CLOCK_ID_2, "clock2", false, null, 50, null),
-                ClockMetadataModel(CLOCK_ID_3, "clock3", false, null, 50, null),
+                ClockMetadataModel(CLOCK_ID_0, true, null, 50, null),
+                ClockMetadataModel(CLOCK_ID_1, false, null, 50, null),
+                ClockMetadataModel(CLOCK_ID_2, false, null, 50, null),
+                ClockMetadataModel(CLOCK_ID_3, false, null, 50, null),
             )
         const val CLOCK_COLOR_ID = "RED"
         const val CLOCK_COLOR_TONE_PROGRESS = 87
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
index 31999fb..c2b42c0 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
@@ -1,19 +1,44 @@
 package com.android.customization.picker.clock.ui
 
+import android.content.res.Resources
 import android.view.View
 import androidx.lifecycle.LifecycleOwner
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.ui.FakeClockViewFactory.Companion.fakeClocks
 import com.android.customization.picker.clock.ui.view.ClockViewFactory
+import com.android.systemui.plugins.ClockConfig
 import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.ClockEvents
+import com.android.systemui.plugins.ClockFaceController
+import java.io.PrintWriter
 
 /**
  * This is a fake [ClockViewFactory]. Only implement the function if it's actually called in a test.
  */
-class FakeClockViewFactory : ClockViewFactory {
+class FakeClockViewFactory(
+    val clockControllers: MutableMap<String, ClockController> = fakeClocks.toMutableMap(),
+) : ClockViewFactory {
 
-    override fun getController(clockId: String): ClockController {
-        TODO("Not yet implemented")
+    class FakeClockController(
+        override var config: ClockConfig,
+    ) : ClockController {
+        override val smallClock: ClockFaceController
+            get() = TODO("Not yet implemented")
+
+        override val largeClock: ClockFaceController
+            get() = TODO("Not yet implemented")
+
+        override val events: ClockEvents
+            get() = TODO("Not yet implemented")
+
+        override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) =
+            TODO("Not yet implemented")
+
+        override fun dump(pw: PrintWriter) = TODO("Not yet implemented")
     }
 
+    override fun getController(clockId: String): ClockController = clockControllers.get(clockId)!!
+
     override fun getLargeView(clockId: String): View {
         TODO("Not yet implemented")
     }
@@ -49,4 +74,20 @@
     override fun unregisterTimeTicker(owner: LifecycleOwner) {
         TODO("Not yet implemented")
     }
+
+    companion object {
+        val fakeClocks =
+            FakeClockPickerRepository.fakeClocks
+                .map { clock ->
+                    clock.clockId to
+                        FakeClockController(
+                            ClockConfig(
+                                id = clock.clockId,
+                                name = "Name: ${clock.clockId}",
+                                description = "Desc: ${clock.clockId}"
+                            )
+                        )
+                }
+                .toMap()
+    }
 }
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index ca6f8c7..813d888 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -16,11 +16,14 @@
 package com.android.customization.picker.clock.ui.viewmodel
 
 import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
 import com.android.customization.picker.clock.data.repository.ClockPickerRepository
 import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
 import com.android.customization.picker.clock.domain.interactor.ClockPickerSnapshotRestorer
 import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.customization.picker.clock.ui.FakeClockViewFactory
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.wallpaper.testing.FakeSnapshotStore
 import com.android.wallpaper.testing.collectLastValue
 import com.google.common.truth.Truth.assertThat
@@ -48,8 +51,7 @@
         FakeClockPickerRepository(
             listOf(
                 ClockMetadataModel(
-                    clockId = "clock0",
-                    name = "clock0",
+                    clockId = FakeClockPickerRepository.CLOCK_ID_0,
                     isSelected = true,
                     selectedColorId = null,
                     colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
@@ -58,13 +60,16 @@
             )
         )
     }
+
     private lateinit var testDispatcher: CoroutineDispatcher
     private lateinit var underTest: ClockCarouselViewModel
     private lateinit var interactor: ClockPickerInteractor
+    private lateinit var clockViewFactory: ClockViewFactory
 
     @Before
     fun setUp() {
         testDispatcher = StandardTestDispatcher()
+        clockViewFactory = FakeClockViewFactory()
         Dispatchers.setMain(testDispatcher)
     }
 
@@ -78,7 +83,9 @@
         underTest =
             ClockCarouselViewModel(
                 getClockPickerInteractor(repositoryWithMultipleClocks),
-                testDispatcher
+                backgroundDispatcher = testDispatcher,
+                clockViewFactory = clockViewFactory,
+                resources = InstrumentationRegistry.getInstrumentation().targetContext.resources,
             )
         val observedSelectedIndex = collectLastValue(underTest.selectedIndex)
         advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)