Merge changes I288c3d8f,Ie6cb75ca,Iadb9ae77,Ib78058d0 into tm-qpr-dev

* changes:
  [TP] Make clock previews tick
  [TP] Smooth scroll to clock color option position
  [TP] Use design clock colors
  [TP] Handle quick update from slider
diff --git a/res/layout/fragment_clock_settings.xml b/res/layout/fragment_clock_settings.xml
index 088ec2a..5208222 100644
--- a/res/layout/fragment_clock_settings.xml
+++ b/res/layout/fragment_clock_settings.xml
@@ -41,6 +41,11 @@
             android:layout_height="match_parent"
             android:layout_gravity="center" />
 
+        <FrameLayout
+            android:id="@+id/clock_host_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center" />
     </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
 
diff --git a/res/values/clock_colors.xml b/res/values/clock_colors.xml
new file mode 100644
index 0000000..1539a92
--- /dev/null
+++ b/res/values/clock_colors.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<resources>
+    <string-array name="clock_color_ids">
+        <item>RED</item>
+        <item>ORANGE</item>
+        <item>YELLOW</item>
+        <item>GREEN</item>
+        <item>BLUE</item>
+        <item>INDIGO</item>
+        <item>VIOLET</item>
+        <item>GRAY</item>
+        <item>TEAL</item>
+    </string-array>
+    <array name="clock_color_names">
+        <item>@string/clock_color_red</item>
+        <item>@string/clock_color_orange</item>
+        <item>@string/clock_color_yellow</item>
+        <item>@string/clock_color_green</item>
+        <item>@string/clock_color_blue</item>
+        <item>@string/clock_color_indigo</item>
+        <item>@string/clock_color_violet</item>
+        <item>@string/clock_color_gray</item>
+        <item>@string/clock_color_teal</item>
+    </array>
+    <array name="clock_colors">
+        <item>#FFA3A7</item>
+        <item>#F7AC69</item>
+        <item>#FFC951</item>
+        <item>#88D86A</item>
+        <item>#8EC8FF</item>
+        <item>#B9AAFF</item>
+        <item>#F6A2FF</item>
+        <item>#B9B9B9</item>
+        <item>#40D9CF</item>
+    </array>
+    <array name="clock_color_tone_min">
+        <item>20</item>
+        <item>20</item>
+        <item>50</item>
+        <item>20</item>
+        <item>20</item>
+        <item>10</item>
+        <item>20</item>
+        <item>0</item>
+        <item>20</item>
+    </array>
+    <array name="clock_color_tone_max">
+        <item>95</item>
+        <item>95</item>
+        <item>95</item>
+        <item>99</item>
+        <item>95</item>
+        <item>95</item>
+        <item>97</item>
+        <item>100</item>
+        <item>99</item>
+    </array>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3bd9e84..18c0103 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -45,6 +45,33 @@
     <!-- Title of a tab to change the clock color. [CHAR LIMIT=15] -->
     <string name="clock_color">Color</string>
 
+    <!-- Title of a clock color red option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_red">Red</string>
+
+    <!-- Title of a clock color orange option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_orange">Orange</string>
+
+    <!-- Title of a clock color yellow option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_yellow">Yellow</string>
+
+    <!-- Title of a clock color green option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_green">Green</string>
+
+    <!-- Title of a clock color blue option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_blue">Blue</string>
+
+    <!-- Title of a clock color indigo option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_indigo">Indigo</string>
+
+    <!-- Title of a clock color violet option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_violet">Violet</string>
+
+    <!-- Title of a clock color grey option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_gray">Grey</string>
+
+    <!-- Title of a clock color teal option that will appear in the description of the custom clock section. [CHAR LIMIT=15] -->
+    <string name="clock_color_teal">Teal</string>
+
     <!-- Title of a tab to change the clock size. [CHAR LIMIT=15] -->
     <string name="clock_size">Size</string>
 
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
index 3474858..ae66ce3 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
@@ -39,12 +39,12 @@
      * Set clock color to the settings.
      *
      * @param selectedColor selected color in the color option list.
-     * @param colorTone color tone from 0 to 100 to apply to the selected color
+     * @param colorToneProgress color tone from 0 to 100 to apply to the selected color
      * @param seedColor the actual clock color after blending the selected color and color tone
      */
     fun setClockColor(
-        @ColorInt selectedColor: Int?,
-        @IntRange(from = 0, to = 100) colorTone: Int,
+        selectedColorId: String?,
+        @IntRange(from = 0, to = 100) colorToneProgress: Int,
         @ColorInt seedColor: Int?,
     )
 
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 e96649b..880a00b 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -86,9 +86,9 @@
                             .getClocks()
                             .find { clockMetadata -> clockMetadata.clockId == currentClockId }
                             ?.toModel(
-                                selectedColor = metadata?.getSelectedColor(),
+                                selectedColorId = metadata?.getSelectedColorId(),
                                 colorTone = metadata?.getColorTone()
-                                        ?: ClockMetadataModel.DEFAULT_COLOR_TONE,
+                                        ?: ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
                                 seedColor = registry.seedColor
                             )
                     trySend(model)
@@ -119,16 +119,16 @@
     }
 
     override fun setClockColor(
-        @ColorInt selectedColor: Int?,
-        @IntRange(from = 0, to = 100) colorTone: Int,
+        selectedColorId: String?,
+        @IntRange(from = 0, to = 100) colorToneProgress: Int,
         @ColorInt seedColor: Int?,
     ) {
         registry.mutateSetting { oldSettings ->
             val newSettings = oldSettings.copy(seedColor = seedColor)
             newSettings.metadata =
                 oldSettings.metadata
-                    .put(KEY_METADATA_SELECTED_COLOR, selectedColor)
-                    .put(KEY_METADATA_COLOR_TONE, colorTone)
+                    .put(KEY_METADATA_SELECTED_COLOR_ID, selectedColorId)
+                    .put(KEY_METADATA_COLOR_TONE_PROGRESS, colorToneProgress)
             newSettings
         }
     }
@@ -153,38 +153,41 @@
         )
     }
 
-    private fun JSONObject.getSelectedColor(): Int? {
-        return if (this.isNull(KEY_METADATA_SELECTED_COLOR)) {
+    private fun JSONObject.getSelectedColorId(): String? {
+        return if (this.isNull(KEY_METADATA_SELECTED_COLOR_ID)) {
             null
         } else {
-            this.getInt(KEY_METADATA_SELECTED_COLOR)
+            this.getString(KEY_METADATA_SELECTED_COLOR_ID)
         }
     }
 
     private fun JSONObject.getColorTone(): Int {
-        return this.optInt(KEY_METADATA_COLOR_TONE, ClockMetadataModel.DEFAULT_COLOR_TONE)
+        return this.optInt(
+            KEY_METADATA_COLOR_TONE_PROGRESS,
+            ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
+        )
     }
 
     /** By default, [ClockMetadataModel] has no color information unless specified. */
     private fun ClockMetadata.toModel(
-        @ColorInt selectedColor: Int? = null,
+        selectedColorId: String? = null,
         @IntRange(from = 0, to = 100) colorTone: Int = 0,
         @ColorInt seedColor: Int? = null,
     ): ClockMetadataModel {
         return ClockMetadataModel(
             clockId = clockId,
             name = name,
-            selectedColor = selectedColor,
-            colorTone = colorTone,
+            selectedColorId = selectedColorId,
+            colorToneProgress = colorTone,
             seedColor = seedColor,
         )
     }
 
     companion object {
         // The selected color in the color option list
-        private const val KEY_METADATA_SELECTED_COLOR = "metadataSelectedColor"
+        private const val KEY_METADATA_SELECTED_COLOR_ID = "metadataSelectedColorId"
 
         // The color tone to apply to the selected color
-        private const val KEY_METADATA_COLOR_TONE = "metadataColorTone"
+        private const val KEY_METADATA_COLOR_TONE_PROGRESS = "metadataColorToneProgress"
     }
 }
diff --git a/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt b/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
index 794706f..6f3657a 100644
--- a/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
+++ b/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
@@ -17,6 +17,8 @@
 
 package com.android.customization.picker.clock.domain.interactor
 
+import androidx.annotation.ColorInt
+import androidx.annotation.IntRange
 import com.android.customization.picker.clock.data.repository.ClockPickerRepository
 import com.android.customization.picker.clock.shared.ClockSize
 import com.android.customization.picker.clock.shared.model.ClockMetadataModel
@@ -35,10 +37,11 @@
     val selectedClockId: Flow<String> =
         repository.selectedClock.map { clock -> clock.clockId }.distinctUntilChanged()
 
-    val selectedColor: Flow<Int?> =
-        repository.selectedClock.map { clock -> clock.selectedColor }.distinctUntilChanged()
+    val selectedColorId: Flow<String?> =
+        repository.selectedClock.map { clock -> clock.selectedColorId }.distinctUntilChanged()
 
-    val colorTone: Flow<Int> = repository.selectedClock.map { clock -> clock.colorTone }
+    val colorToneProgress: Flow<Int> =
+        repository.selectedClock.map { clock -> clock.colorToneProgress }
 
     val seedColor: Flow<Int?> = repository.selectedClock.map { clock -> clock.seedColor }
 
@@ -48,8 +51,12 @@
         repository.setSelectedClock(clockId)
     }
 
-    fun setClockColor(selectedColor: Int?, colorTone: Int, seedColor: Int?) {
-        repository.setClockColor(selectedColor, colorTone, seedColor)
+    fun setClockColor(
+        selectedColorId: String?,
+        @IntRange(from = 0, to = 100) colorToneProgress: Int,
+        @ColorInt seedColor: Int?,
+    ) {
+        repository.setClockColor(selectedColorId, colorToneProgress, seedColor)
     }
 
     suspend fun setClockSize(size: ClockSize) {
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 72aeca6..bd87ba6 100644
--- a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
+++ b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
@@ -24,11 +24,11 @@
 data class ClockMetadataModel(
     val clockId: String,
     val name: String,
-    @ColorInt val selectedColor: Int?,
-    @IntRange(from = 0, to = 100) val colorTone: Int,
+    val selectedColorId: String?,
+    @IntRange(from = 0, to = 100) val colorToneProgress: Int,
     @ColorInt val seedColor: Int?,
 ) {
     companion object {
-        const val DEFAULT_COLOR_TONE = 50
+        const val DEFAULT_COLOR_TONE_PROGRESS = 75
     }
 }
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
index 6c72a5b..9ad735d 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -15,7 +15,6 @@
  */
 package com.android.customization.picker.clock.ui.binder
 
-import android.view.View
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.core.view.isVisible
@@ -24,6 +23,7 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.customization.picker.clock.ui.view.ClockCarouselView
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
 import com.android.wallpaper.R
 import kotlinx.coroutines.launch
@@ -43,7 +43,7 @@
         carouselView: ClockCarouselView,
         singleClockView: ViewGroup,
         viewModel: ClockCarouselViewModel,
-        clockViewFactory: (clockId: String) -> View,
+        clockViewFactory: ClockViewFactory,
         lifecycleOwner: LifecycleOwner,
     ): Binding {
         val singleClockHostView =
@@ -56,7 +56,7 @@
                     viewModel.allClockIds.collect { allClockIds ->
                         carouselView.setUpClockCarouselView(
                             clockIds = allClockIds,
-                            onGetClockPreview = clockViewFactory,
+                            onGetClockPreview = { clockId -> clockViewFactory.getView(clockId) },
                             onClockSelected = { clockId -> viewModel.setSelectedClock(clockId) },
                         )
                     }
@@ -69,13 +69,17 @@
                 }
 
                 launch {
+                    viewModel.seedColor.collect { clockViewFactory.updateColorForAllClocks(it) }
+                }
+
+                launch {
                     viewModel.isSingleClockViewVisible.collect { singleClockView.isVisible = it }
                 }
 
                 launch {
                     viewModel.clockId.collect { clockId ->
                         singleClockHostView.removeAllViews()
-                        val clockView = clockViewFactory(clockId)
+                        val clockView = clockViewFactory.getView(clockId)
                         // The clock view might still be attached to an existing parent. Detach
                         // before adding to another parent.
                         (clockView.parent as? ViewGroup)?.removeView(clockView)
@@ -84,6 +88,15 @@
                 }
             }
         }
+
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+                clockViewFactory.registerTimeTicker()
+            }
+            // When paused
+            clockViewFactory.unregisterTimeTicker()
+        }
+
         return object : Binding {
             override fun show() {
                 viewModel.showClockCarousel(true)
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
index 62d7217..66d9251 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -16,6 +16,8 @@
 package com.android.customization.picker.clock.ui.binder
 
 import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
 import android.widget.SeekBar
 import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
@@ -28,10 +30,12 @@
 import com.android.customization.picker.clock.shared.ClockSize
 import com.android.customization.picker.clock.ui.adapter.ClockSettingsTabAdapter
 import com.android.customization.picker.clock.ui.view.ClockSizeRadioButtonGroup
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
 import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
 import com.android.customization.picker.color.ui.adapter.ColorOptionAdapter
 import com.android.customization.picker.common.ui.view.ItemSpacing
 import com.android.wallpaper.R
+import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.launch
 
 /** Bind between the clock settings screen and its view model. */
@@ -39,8 +43,11 @@
     fun bind(
         view: View,
         viewModel: ClockSettingsViewModel,
+        clockViewFactory: ClockViewFactory,
         lifecycleOwner: LifecycleOwner,
     ) {
+        val clockHostView: FrameLayout = view.requireViewById(R.id.clock_host_view)
+
         val tabView: RecyclerView = view.requireViewById(R.id.tabs)
         val tabAdapter = ClockSettingsTabAdapter()
         tabView.adapter = tabAdapter
@@ -82,6 +89,25 @@
         val colorOptionContainer = view.requireViewById<View>(R.id.color_picker_container)
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                launch {
+                    viewModel.selectedClockId
+                        .mapNotNull { it }
+                        .collect { clockId ->
+                            val clockView = clockViewFactory.getView(clockId)
+                            (clockView.parent as? ViewGroup)?.removeView(clockView)
+                            clockHostView.removeAllViews()
+                            clockHostView.addView(clockView)
+                        }
+                }
+
+                launch {
+                    viewModel.seedColor.collect { seedColor ->
+                        viewModel.selectedClockId.value?.let { selectedClockId ->
+                            clockViewFactory.updateColor(selectedClockId, seedColor)
+                        }
+                    }
+                }
+
                 launch { viewModel.tabs.collect { tabAdapter.setItems(it) } }
 
                 launch {
@@ -106,6 +132,18 @@
                 }
 
                 launch {
+                    viewModel.selectedColorOptionPosition.collect { selectedPosition ->
+                        if (selectedPosition != -1) {
+                            // We use "post" because we need to give the adapter item a pass to
+                            // update the view.
+                            colorOptionContainerView.post {
+                                colorOptionContainerView.smoothScrollToPosition(selectedPosition)
+                            }
+                        }
+                    }
+                }
+
+                launch {
                     viewModel.selectedClockSize.collect { size ->
                         when (size) {
                             ClockSize.DYNAMIC -> {
@@ -131,5 +169,13 @@
                 }
             }
         }
+
+        lifecycleOwner.lifecycleScope.launch {
+            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
+                clockViewFactory.registerTimeTicker()
+            }
+            // When paused
+            clockViewFactory.unregisterTimeTicker()
+        }
     }
 }
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 9b6d737..ef1a5ef 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -24,6 +24,7 @@
 import androidx.lifecycle.get
 import com.android.customization.module.ThemePickerInjector
 import com.android.customization.picker.clock.ui.binder.ClockSettingsBinder
+import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
 import com.android.wallpaper.R
 import com.android.wallpaper.module.InjectorProvider
 import com.android.wallpaper.picker.AppbarFragment
@@ -95,6 +96,16 @@
                         onWallpaperColorChanged = { colors ->
                             colorViewModel.setLockWallpaperColors(colors)
                         },
+                        initialExtrasProvider = {
+                            Bundle().apply {
+                                // Hide the clock from the system UI rendered preview so we can
+                                // place the carousel on top of it.
+                                putBoolean(
+                                    ClockPreviewConstants.KEY_HIDE_CLOCK,
+                                    true,
+                                )
+                            }
+                        },
                     ),
                 lifecycleOwner = this,
                 offsetToStart = displayUtils.isOnWallpaperDisplay(activity),
@@ -111,6 +122,7 @@
                     ),
                 )
                 .get(),
+            injector.getClockViewFactory(activity),
             this@ClockSettingsFragment,
         )
 
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
index 488dd08..7f480de 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
@@ -17,21 +17,45 @@
 
 import android.app.Activity
 import android.view.View
+import androidx.annotation.ColorInt
 import com.android.systemui.plugins.ClockController
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.wallpaper.R
 import com.android.wallpaper.util.ScreenSizeCalculator
+import com.android.wallpaper.util.TimeUtils.TimeTicker
 
 class ClockViewFactory(
     private val activity: Activity,
     private val registry: ClockRegistry,
 ) {
     private val clockControllers: HashMap<String, ClockController> = HashMap()
+    private var ticker: TimeTicker? = null
 
     fun getView(clockId: String): View {
         return (clockControllers[clockId] ?: initClockController(clockId)).largeClock.view
     }
 
+    fun updateColorForAllClocks(@ColorInt seedColor: Int?) {
+        clockControllers.values.forEach { it.events.onSeedColorChanged(seedColor = seedColor) }
+    }
+
+    fun updateColor(clockId: String, @ColorInt seedColor: Int?) {
+        return (clockControllers[clockId] ?: initClockController(clockId))
+            .events
+            .onSeedColorChanged(seedColor)
+    }
+
+    fun registerTimeTicker() {
+        ticker =
+            TimeTicker.registerNewReceiver(activity.applicationContext) {
+                clockControllers.values.forEach { it.largeClock.events.onTimeTick() }
+            }
+    }
+
+    fun unregisterTimeTicker() {
+        activity.applicationContext.unregisterReceiver(ticker)
+    }
+
     private fun initClockController(clockId: String): ClockController {
         val controller =
             registry.createExampleClock(clockId).also { it?.initialize(activity.resources, 0f, 0f) }
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 8fe9dca..60a9e85 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -42,6 +42,8 @@
             allClocks.map { it.clockId }
         }
 
+    val seedColor: Flow<Int?> = interactor.seedColor
+
     private val shouldShowCarousel = MutableStateFlow(false)
     val isCarouselVisible: Flow<Boolean> =
         combine(allClockIds.map { it.size > 1 }.distinctUntilChanged(), shouldShowCarousel) {
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt
new file mode 100644
index 0000000..65ebc79
--- /dev/null
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockColorViewModel.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.ui.viewmodel
+
+import android.annotation.ColorInt
+import android.content.res.Resources
+import android.graphics.Color
+import androidx.core.content.res.getStringOrThrow
+import com.android.wallpaper.R
+
+/** The view model that defines custom clock colors. */
+data class ClockColorViewModel(
+    val colorId: String,
+    val colorName: String?,
+    @ColorInt val color: Int,
+    private val colorToneMin: Double,
+    private val colorToneMax: Double,
+) {
+
+    fun getColorTone(progress: Int): Double {
+        return colorToneMin + (progress.toDouble() * (colorToneMax - colorToneMin)) / 100
+    }
+
+    companion object {
+        const val DEFAULT_COLOR_TONE_MIN = 0
+        const val DEFAULT_COLOR_TONE_MAX = 100
+
+        fun getPresetColorMap(resources: Resources): Map<String, ClockColorViewModel> {
+            val ids = resources.obtainTypedArray(R.array.clock_color_ids)
+            val names = resources.obtainTypedArray(R.array.clock_color_names)
+            val colors = resources.obtainTypedArray(R.array.clock_colors)
+            val colorToneMinList = resources.obtainTypedArray(R.array.clock_color_tone_min)
+            val colorToneMaxList = resources.obtainTypedArray(R.array.clock_color_tone_max)
+            return buildList {
+                    for (i in 0 until ids.length()) {
+                        add(
+                            ClockColorViewModel(
+                                ids.getStringOrThrow(i),
+                                names.getString(i),
+                                colors.getColor(i, Color.TRANSPARENT),
+                                colorToneMinList.getInt(i, DEFAULT_COLOR_TONE_MIN).toDouble(),
+                                colorToneMaxList.getInt(i, DEFAULT_COLOR_TONE_MAX).toDouble(),
+                            )
+                        )
+                    }
+                }
+                .associateBy { it.colorId }
+                .also {
+                    ids.recycle()
+                    names.recycle()
+                    colors.recycle()
+                    colorToneMinList.recycle()
+                    colorToneMaxList.recycle()
+                }
+        }
+    }
+}
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
index 9239c0a..008a125 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModel.kt
@@ -22,15 +22,20 @@
 import com.android.wallpaper.R
 import java.util.Locale
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.map
 
 /** View model for the clock section view on the lockscreen customization surface. */
 class ClockSectionViewModel(context: Context, interactor: ClockPickerInteractor) {
     val appContext: Context = context.applicationContext
+    val clockColorMap: Map<String, ClockColorViewModel> =
+        ClockColorViewModel.getPresetColorMap(appContext.resources)
     val selectedClockColorAndSizeText: Flow<String> =
-        interactor.selectedClockSize.map { selectedClockSize ->
-            // TODO (b/241966062) Finalize the colors and their names
-            val colorText = "Violet"
+        combine(interactor.selectedColorId, interactor.selectedClockSize, ::Pair).map {
+            (selectedColorId, selectedClockSize) ->
+            val colorText =
+                clockColorMap[selectedColorId]?.colorName
+                    ?: context.getString(R.string.default_theme_title)
             val sizeText =
                 when (selectedClockSize) {
                     ClockSize.SMALL -> appContext.getString(R.string.clock_size_small)
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
index 06fd2af..23fbc7e 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -57,13 +57,22 @@
         SIZE,
     }
 
-    val selectedColor: StateFlow<Int?> =
-        clockPickerInteractor.selectedColor.stateIn(viewModelScope, SharingStarted.Eagerly, null)
+    val colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
 
-    private val sliderProgressColorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE)
+    val selectedClockId: StateFlow<String?> =
+        clockPickerInteractor.selectedClockId
+            .distinctUntilChanged()
+            .stateIn(viewModelScope, SharingStarted.Eagerly, null)
+
+    val selectedColorId: StateFlow<String?> =
+        clockPickerInteractor.selectedColorId.stateIn(viewModelScope, SharingStarted.Eagerly, null)
+
+    private val sliderColorToneProgress =
+        MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
     val isSliderEnabled: Flow<Boolean> =
-        clockPickerInteractor.selectedColor.map { it != null }.distinctUntilChanged()
-    val sliderProgress: Flow<Int> = merge(clockPickerInteractor.colorTone, sliderProgressColorTone)
+        clockPickerInteractor.selectedColorId.map { it != null }.distinctUntilChanged()
+    val sliderProgress: Flow<Int> =
+        merge(clockPickerInteractor.colorToneProgress, sliderColorToneProgress)
 
     private val _seedColor: MutableStateFlow<Int?> = MutableStateFlow(null)
     val seedColor: Flow<Int?> = merge(clockPickerInteractor.seedColor, _seedColor)
@@ -71,29 +80,37 @@
     /**
      * The slider color tone updates are quick. Do not set color tone and the blended color to the
      * settings until [onSliderProgressStop] is called. Update to a locally cached temporary
-     * [sliderProgressColorTone] and [_seedColor] instead.
+     * [sliderColorToneProgress] and [_seedColor] instead.
      */
     fun onSliderProgressChanged(progress: Int) {
-        sliderProgressColorTone.value = progress
-        val color = selectedColor.value
-        if (color != null) {
-            _seedColor.value = blendColorWithTone(color, progress)
-        }
+        sliderColorToneProgress.value = progress
+        val selectedColorId = selectedColorId.value ?: return
+        val clockColorViewModel = colorMap[selectedColorId] ?: return
+        _seedColor.value =
+            blendColorWithTone(
+                color = clockColorViewModel.color,
+                colorTone = clockColorViewModel.getColorTone(progress),
+            )
     }
 
     fun onSliderProgressStop(progress: Int) {
-        val color = selectedColor.value ?: return
+        val selectedColorId = selectedColorId.value ?: return
+        val clockColorViewModel = colorMap[selectedColorId] ?: return
         clockPickerInteractor.setClockColor(
-            selectedColor = color,
-            colorTone = progress,
-            seedColor = blendColorWithTone(color = color, colorTone = progress)
+            selectedColorId = selectedColorId,
+            colorToneProgress = progress,
+            seedColor =
+                blendColorWithTone(
+                    color = clockColorViewModel.color,
+                    colorTone = clockColorViewModel.getColorTone(progress),
+                )
         )
     }
 
     @OptIn(ExperimentalCoroutinesApi::class)
     val colorOptions: StateFlow<List<ColorOptionViewModel>> =
-        combine(colorPickerInteractor.colorOptions, clockPickerInteractor.selectedColor, ::Pair)
-            .mapLatest { (colorOptions, selectedColor) ->
+        combine(colorPickerInteractor.colorOptions, clockPickerInteractor.selectedColorId, ::Pair)
+            .mapLatest { (colorOptions, selectedColorId) ->
                 // Use mapLatest and delay(100) here to prevent too many selectedClockColor update
                 // events from ClockRegistry upstream, caused by sliding the saturation level bar.
                 delay(COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
@@ -104,35 +121,30 @@
                                 ?.colorOption as? ColorSeedOption)
                             ?.toColorOptionViewModel(
                                 context,
-                                selectedColor,
+                                selectedColorId,
                             )
                             ?: (colorOptions[ColorType.BASIC_COLOR]
                                     ?.find { it.isSelected }
                                     ?.colorOption as? ColorBundle)
                                 ?.toColorOptionViewModel(
                                     context,
-                                    selectedColor,
+                                    selectedColorId,
                                 )
                     if (defaultThemeColorOptionViewModel != null) {
                         add(defaultThemeColorOptionViewModel)
                     }
 
-                    val selectedColorPosition =
-                        if (selectedColor != null) {
-                            COLOR_SET_LIST.indexOf(selectedColor)
-                        } else {
-                            -1
-                        }
+                    val selectedColorPosition = colorMap.keys.indexOf(selectedColorId)
 
-                    COLOR_SET_LIST.forEachIndexed { index, color ->
+                    colorMap.values.forEachIndexed { index, colorModel ->
                         val isSelected = selectedColorPosition == index
-                        val colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE
+                        val colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
                         add(
                             ColorOptionViewModel(
-                                color0 = color,
-                                color1 = color,
-                                color2 = color,
-                                color3 = color,
+                                color0 = colorModel.color,
+                                color1 = colorModel.color,
+                                color2 = colorModel.color,
+                                color3 = colorModel.color,
                                 contentDescription =
                                     context.getString(
                                         R.string.content_description_color_option,
@@ -145,12 +157,15 @@
                                     } else {
                                         {
                                             clockPickerInteractor.setClockColor(
-                                                selectedColor = color,
-                                                colorTone = colorTone,
+                                                selectedColorId = colorModel.colorId,
+                                                colorToneProgress = colorToneProgress,
                                                 seedColor =
                                                     blendColorWithTone(
-                                                        color = color,
-                                                        colorTone = colorTone,
+                                                        color = colorModel.color,
+                                                        colorTone =
+                                                            colorModel.getColorTone(
+                                                                colorToneProgress,
+                                                            ),
                                                     ),
                                             )
                                         }
@@ -166,9 +181,13 @@
                 initialValue = emptyList(),
             )
 
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val selectedColorOptionPosition: Flow<Int> =
+        colorOptions.mapLatest { it.indexOfFirst { colorOption -> colorOption.isSelected } }
+
     private fun ColorSeedOption.toColorOptionViewModel(
         context: Context,
-        selectedColor: Int?,
+        selectedColorId: String?,
     ): ColorOptionViewModel {
         val colors = previewInfo.resolveColors(context.resources)
         return ColorOptionViewModel(
@@ -178,15 +197,15 @@
             color3 = colors[3],
             contentDescription = getContentDescription(context).toString(),
             title = context.getString(R.string.default_theme_title),
-            isSelected = selectedColor == null,
+            isSelected = selectedColorId == null,
             onClick =
-                if (selectedColor == null) {
+                if (selectedColorId == null) {
                     null
                 } else {
                     {
                         clockPickerInteractor.setClockColor(
-                            selectedColor = null,
-                            colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE,
+                            selectedColorId = null,
+                            colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
                             seedColor = null,
                         )
                     }
@@ -196,7 +215,7 @@
 
     private fun ColorBundle.toColorOptionViewModel(
         context: Context,
-        selectedColor: Int?
+        selectedColorId: String?
     ): ColorOptionViewModel {
         val primaryColor = previewInfo.resolvePrimaryColor(context.resources)
         val secondaryColor = previewInfo.resolveSecondaryColor(context.resources)
@@ -207,15 +226,15 @@
             color3 = secondaryColor,
             contentDescription = getContentDescription(context).toString(),
             title = context.getString(R.string.default_theme_title),
-            isSelected = selectedColor == null,
+            isSelected = selectedColorId == null,
             onClick =
-                if (selectedColor == null) {
+                if (selectedColorId == null) {
                     null
                 } else {
                     {
                         clockPickerInteractor.setClockColor(
-                            selectedColor = null,
-                            colorTone = ClockMetadataModel.DEFAULT_COLOR_TONE,
+                            selectedColorId = null,
+                            colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
                             seedColor = null,
                         )
                     }
@@ -258,24 +277,12 @@
         }
 
     companion object {
-        // TODO (b/241966062) The color integers here are temporary for dev purposes. We need to
-        //                    finalize the overridden colors.
-        val COLOR_SET_LIST =
-            listOf(
-                -786432,
-                -3648768,
-                -9273600,
-                -16739840,
-                -9420289,
-                -6465837,
-                -5032719,
-            )
+        private val helperColorLab: DoubleArray by lazy { DoubleArray(3) }
 
-        fun blendColorWithTone(color: Int, colorTone: Int): Int {
-            val helperColorLab: DoubleArray by lazy { DoubleArray(3) }
+        fun blendColorWithTone(color: Int, colorTone: Double): Int {
             ColorUtils.colorToLAB(color, helperColorLab)
             return ColorUtils.LABToColor(
-                colorTone.toDouble(),
+                colorTone,
                 helperColorLab[1],
                 helperColorLab[2],
             )
diff --git a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
index 0b197b4..700439b 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -79,7 +79,7 @@
                     carouselView = carouselView,
                     singleClockView = singleClockView,
                     viewModel = clockCarouselViewModel,
-                    clockViewFactory = { clockId -> clockViewFactory.getView(clockId) },
+                    clockViewFactory = clockViewFactory,
                     lifecycleOwner = lifecycleOwner,
                 )
             onScreenSwitched(
diff --git a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 918cfb1..2ef4e97 100644
--- a/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -15,6 +15,7 @@
  */
 package com.android.customization.picker.clock.data.repository
 
+import android.graphics.Color
 import androidx.annotation.ColorInt
 import androidx.annotation.IntRange
 import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository.Companion.fakeClocks
@@ -31,13 +32,13 @@
     override val allClocks: Flow<List<ClockMetadataModel>> = MutableStateFlow(clocks).asStateFlow()
 
     private val selectedClockId = MutableStateFlow(fakeClocks[0].clockId)
-    @ColorInt private val selectedColor = MutableStateFlow<Int?>(null)
-    private val colorTone = MutableStateFlow<Int>(ClockMetadataModel.DEFAULT_COLOR_TONE)
+    @ColorInt private val selectedColorId = MutableStateFlow<String?>(null)
+    private val colorTone = MutableStateFlow(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
     @ColorInt private val seedColor = MutableStateFlow<Int?>(null)
     override val selectedClock: Flow<ClockMetadataModel> =
         combine(
             selectedClockId,
-            selectedColor,
+            selectedColorId,
             colorTone,
             seedColor,
         ) { selectedClockId, selectedColor, colorTone, seedColor ->
@@ -60,12 +61,12 @@
     }
 
     override fun setClockColor(
-        @ColorInt selectedColor: Int?,
-        @IntRange(from = 0, to = 100) colorTone: Int,
+        selectedColorId: String?,
+        @IntRange(from = 0, to = 100) colorToneProgress: Int,
         @ColorInt seedColor: Int?,
     ) {
-        this.selectedColor.value = selectedColor
-        this.colorTone.value = colorTone
+        this.selectedColorId.value = selectedColorId
+        this.colorTone.value = colorToneProgress
         this.seedColor.value = seedColor
     }
 
@@ -81,7 +82,8 @@
                 ClockMetadataModel("clock2", "clock2", null, 50, null),
                 ClockMetadataModel("clock3", "clock3", null, 50, null),
             )
-        val clockColor = 0
-        val clockColorTone = 87
+        const val CLOCK_COLOR_ID = "RED"
+        const val CLOCK_COLOR_TONE_PROGRESS = 87
+        const val SEED_COLOR = Color.RED
     }
 }
diff --git a/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
index 01bfce1..cd41d7d 100644
--- a/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
+++ b/tests/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractorTest.kt
@@ -56,16 +56,18 @@
 
     @Test
     fun setColor() = runTest {
-        val observedSelectedColor = collectLastValue(underTest.selectedColor)
-        val observedColorTone = collectLastValue(underTest.colorTone)
+        val observedSelectedColor = collectLastValue(underTest.selectedColorId)
+        val observedColorToneProgress = collectLastValue(underTest.colorToneProgress)
         val observedSeedColor = collectLastValue(underTest.seedColor)
         underTest.setClockColor(
-            FakeClockPickerRepository.clockColor,
-            FakeClockPickerRepository.clockColorTone,
-            FakeClockPickerRepository.clockColor,
+            FakeClockPickerRepository.CLOCK_COLOR_ID,
+            FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS,
+            FakeClockPickerRepository.SEED_COLOR,
         )
-        Truth.assertThat(observedSelectedColor()).isEqualTo(FakeClockPickerRepository.clockColor)
-        Truth.assertThat(observedColorTone()).isEqualTo(FakeClockPickerRepository.clockColorTone)
-        Truth.assertThat(observedSeedColor()).isEqualTo(FakeClockPickerRepository.clockColor)
+        Truth.assertThat(observedSelectedColor())
+            .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_ID)
+        Truth.assertThat(observedColorToneProgress())
+            .isEqualTo(FakeClockPickerRepository.CLOCK_COLOR_TONE_PROGRESS)
+        Truth.assertThat(observedSeedColor()).isEqualTo(FakeClockPickerRepository.SEED_COLOR)
     }
 }
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index ea1311f..63f77bd 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -46,7 +46,7 @@
                     "clock0",
                     "clock0",
                     null,
-                    ClockMetadataModel.DEFAULT_COLOR_TONE,
+                    ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
                     null,
                 ),
             )
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
new file mode 100644
index 0000000..61976ad
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSectionViewModelTest.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.wallpaper.testing.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class ClockSectionViewModelTest {
+
+    private lateinit var clockColorMap: Map<String, ClockColorViewModel>
+    private lateinit var interactor: ClockPickerInteractor
+    private lateinit var underTest: ClockSectionViewModel
+
+    @Before
+    fun setUp() {
+        val testDispatcher = StandardTestDispatcher()
+        Dispatchers.setMain(testDispatcher)
+        val context = InstrumentationRegistry.getInstrumentation().targetContext
+        clockColorMap = ClockColorViewModel.getPresetColorMap(context.resources)
+        interactor = ClockPickerInteractor(FakeClockPickerRepository())
+        underTest =
+            ClockSectionViewModel(
+                context,
+                interactor,
+            )
+    }
+
+    @After
+    fun tearDown() {
+        Dispatchers.resetMain()
+    }
+
+    @Test
+    fun setSelectedClock() = runTest {
+        val colorRed = clockColorMap.values.first()
+        val observedSelectedClockColorAndSizeText =
+            collectLastValue(underTest.selectedClockColorAndSizeText)
+        interactor.setClockColor(
+            colorRed.colorId,
+            ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
+            ClockSettingsViewModel.blendColorWithTone(
+                colorRed.color,
+                colorRed.getColorTone(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS),
+            )
+        )
+        interactor.setClockSize(ClockSize.DYNAMIC)
+        assertThat(observedSelectedClockColorAndSizeText()).isEqualTo("Red, dynamic")
+    }
+}
diff --git a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
similarity index 77%
rename from tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
rename to tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
index 10994c7..d53288d 100644
--- a/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsTabViewModelTest.kt
+++ b/tests/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModelTest.kt
@@ -6,6 +6,7 @@
 import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
 import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
 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
@@ -31,10 +32,10 @@
 @RunWith(JUnit4::class)
 class ClockSettingsViewModelTest {
 
-    private lateinit var underTest: ClockSettingsViewModel
-    private lateinit var colorPickerInteractor: ColorPickerInteractor
-    private lateinit var store: FakeSnapshotStore
     private lateinit var context: Context
+    private lateinit var colorPickerInteractor: ColorPickerInteractor
+    private lateinit var underTest: ClockSettingsViewModel
+    private lateinit var colorMap: Map<String, ClockColorViewModel>
 
     @Before
     fun setUp() {
@@ -46,7 +47,7 @@
                 repository = FakeColorPickerRepository(context = context),
                 snapshotRestorer = {
                     ColorPickerSnapshotRestorer(interactor = colorPickerInteractor).apply {
-                        runBlocking { setUpSnapshotRestorer(store = store) }
+                        runBlocking { setUpSnapshotRestorer(store = FakeSnapshotStore()) }
                     }
                 },
             )
@@ -57,6 +58,7 @@
                     colorPickerInteractor = colorPickerInteractor,
                 )
                 .create(ClockSettingsViewModel::class.java)
+        colorMap = ClockColorViewModel.getPresetColorMap(context.resources)
     }
 
     @After
@@ -80,16 +82,34 @@
     @Test
     fun setSelectedColor() = runTest {
         val observedClockColorOptions = collectLastValue(underTest.colorOptions)
+        val observedSelectedColorOptionPosition =
+            collectLastValue(underTest.selectedColorOptionPosition)
+        val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+        val observedSeedColor = collectLastValue(underTest.seedColor)
         // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
         advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
         assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
         assertThat(observedClockColorOptions()!![0].onClick).isNull()
+        assertThat(observedSelectedColorOptionPosition()).isEqualTo(0)
 
         observedClockColorOptions()!![1].onClick?.invoke()
         // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
         advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
         assertThat(observedClockColorOptions()!![1].isSelected).isTrue()
         assertThat(observedClockColorOptions()!![1].onClick).isNull()
+        assertThat(observedSelectedColorOptionPosition()).isEqualTo(1)
+        assertThat(observedSliderProgress())
+            .isEqualTo(ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS)
+        val expectedSelectedColorModel = colorMap.values.first() // RED
+        assertThat(observedSeedColor())
+            .isEqualTo(
+                ClockSettingsViewModel.blendColorWithTone(
+                    expectedSelectedColorModel.color,
+                    expectedSelectedColorModel.getColorTone(
+                        ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS
+                    ),
+                )
+            )
     }
 
     @Test
@@ -97,12 +117,14 @@
         val observedClockColorOptions = collectLastValue(underTest.colorOptions)
         val observedIsSliderEnabled = collectLastValue(underTest.isSliderEnabled)
         val observedSliderProgress = collectLastValue(underTest.sliderProgress)
+        val observedSeedColor = collectLastValue(underTest.seedColor)
         // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
         advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
         assertThat(observedClockColorOptions()!![0].isSelected).isTrue()
         assertThat(observedIsSliderEnabled()).isFalse()
 
         observedClockColorOptions()!![1].onClick?.invoke()
+
         // Advance COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS since there is a delay from colorOptions
         advanceTimeBy(ClockSettingsViewModel.COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS)
         assertThat(observedIsSliderEnabled()).isTrue()
@@ -112,6 +134,14 @@
         val targetProgress2 = 55
         underTest.onSliderProgressStop(targetProgress2)
         assertThat(observedSliderProgress()).isEqualTo(targetProgress2)
+        val expectedSelectedColorModel = colorMap.values.first() // RED
+        assertThat(observedSeedColor())
+            .isEqualTo(
+                ClockSettingsViewModel.blendColorWithTone(
+                    expectedSelectedColorModel.color,
+                    expectedSelectedColorModel.getColorTone(targetProgress2),
+                )
+            )
     }
 
     @Test