Merge "Import translations. DO NOT MERGE ANYWHERE" into tm-qpr-dev
diff --git a/res/layout/clock_carousel.xml b/res/layout/clock_carousel.xml
index cfc7e4e..35defd6 100644
--- a/res/layout/clock_carousel.xml
+++ b/res/layout/clock_carousel.xml
@@ -111,12 +111,12 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        app:layout_constraintGuide_begin="100dp" />
+        app:layout_constraintGuide_begin="@dimen/clock_carousel_guideline_margin" />
 
     <androidx.constraintlayout.widget.Guideline
         android:id="@+id/guideline_end"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        app:layout_constraintGuide_end="100dp" />
+        app:layout_constraintGuide_end="@dimen/clock_carousel_guideline_margin" />
 </androidx.constraintlayout.motion.widget.MotionLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f79d9b1..30d71e3 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -154,4 +154,5 @@
     <dimen name="clock_carousel_item_width">190dp</dimen>
     <dimen name="clock_carousel_item_height">380dp</dimen>
     <dimen name="clock_carousel_item_margin">16dp</dimen>
+    <dimen name="clock_carousel_guideline_margin">140dp</dimen>
 </resources>
diff --git a/res/xml/carousel_scene.xml b/res/xml/carousel_scene.xml
index 8c6738b..d94f32b 100644
--- a/res/xml/carousel_scene.xml
+++ b/res/xml/carousel_scene.xml
@@ -42,6 +42,8 @@
             android:id="@+id/item_view_0"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -59,6 +61,8 @@
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -69,6 +73,8 @@
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -86,6 +92,8 @@
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -96,6 +104,8 @@
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -113,6 +123,8 @@
             android:id="@+id/item_view_4"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
+            android:scaleX="0.5"
+            android:scaleY="0.5"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 90a213b..c5f0b76 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -21,7 +21,6 @@
 import com.android.customization.model.theme.OverlayManagerCompat
 import com.android.customization.model.theme.ThemeBundleProvider
 import com.android.customization.model.theme.ThemeManager
-import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
 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
@@ -48,17 +47,11 @@
         context: Context,
     ): KeyguardQuickAffordancePickerInteractor
 
-    fun getClockRegistryProvider(context: Context): ClockRegistryProvider
+    fun getClockRegistry(context: Context): ClockRegistry
 
-    fun getClockPickerInteractor(
-        context: Context,
-        clockRegistry: ClockRegistry,
-    ): ClockPickerInteractor
+    fun getClockPickerInteractor(context: Context): ClockPickerInteractor
 
-    fun getClockSectionViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry,
-    ): ClockSectionViewModel
+    fun getClockSectionViewModel(context: Context): ClockSectionViewModel
 
     fun getColorPickerInteractor(
         context: Context,
@@ -70,18 +63,9 @@
         wallpaperColorsViewModel: WallpaperColorsViewModel,
     ): ColorPickerViewModel.Factory
 
-    fun getClockCarouselViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry,
-    ): ClockCarouselViewModel
+    fun getClockCarouselViewModel(context: Context): ClockCarouselViewModel
 
-    fun getClockViewFactory(
-        activity: Activity,
-        registry: ClockRegistry,
-    ): ClockViewFactory
+    fun getClockViewFactory(activity: Activity): ClockViewFactory
 
-    fun getClockSettingsViewModelFactory(
-        context: Context,
-        registry: ClockRegistry,
-    ): ClockSettingsViewModel.Factory
+    fun getClockSettingsViewModelFactory(context: Context): ClockSettingsViewModel.Factory
 }
diff --git a/src/com/android/customization/module/DefaultCustomizationSections.java b/src/com/android/customization/module/DefaultCustomizationSections.java
index 7653095..482ece01 100644
--- a/src/com/android/customization/module/DefaultCustomizationSections.java
+++ b/src/com/android/customization/module/DefaultCustomizationSections.java
@@ -16,14 +16,13 @@
 import com.android.customization.model.themedicon.ThemedIconSwitchProvider;
 import com.android.customization.model.themedicon.domain.interactor.ThemedIconInteractor;
 import com.android.customization.model.themedicon.domain.interactor.ThemedIconSnapshotRestorer;
-import com.android.customization.picker.clock.data.repository.ClockRegistryProvider;
+import com.android.customization.picker.clock.ui.view.ClockViewFactory;
+import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel;
 import com.android.customization.picker.color.ui.section.ColorSectionController2;
 import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel;
 import com.android.customization.picker.notifications.ui.section.NotificationSectionController;
 import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel;
 import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController;
-import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController.ClockCarouselViewModelProvider;
-import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController.ClockViewFactoryProvider;
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor;
 import com.android.customization.picker.quickaffordance.ui.section.KeyguardQuickAffordanceSectionController;
 import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
@@ -55,11 +54,8 @@
             mKeyguardQuickAffordancePickerViewModelFactory;
     private final NotificationSectionViewModel.Factory mNotificationSectionViewModelFactory;
     private final BaseFlags mFlags;
-    private final ClockRegistryProvider mClockRegistryProvider;
-    private final PreviewWithClockCarouselSectionController.ClockCarouselViewModelProvider
-            mClockCarouselViewModelProvider;
-    private final PreviewWithClockCarouselSectionController.ClockViewFactoryProvider
-            mClockViewFactoryProvider;
+    private final ClockCarouselViewModel mClockCarouselViewModel;
+    private final ClockViewFactory mClockViewFactory;
     private final DarkModeSnapshotRestorer mDarkModeSnapshotRestorer;
     private final ThemedIconSnapshotRestorer mThemedIconSnapshotRestorer;
     private final ThemedIconInteractor mThemedIconInteractor;
@@ -71,9 +67,8 @@
                     keyguardQuickAffordancePickerViewModelFactory,
             NotificationSectionViewModel.Factory notificationSectionViewModelFactory,
             BaseFlags flags,
-            ClockRegistryProvider clockRegistryProvider,
-            ClockCarouselViewModelProvider clockCarouselViewModelProvider,
-            ClockViewFactoryProvider clockViewFactoryProvider,
+            ClockCarouselViewModel clockCarouselViewModel,
+            ClockViewFactory clockViewFactory,
             DarkModeSnapshotRestorer darkModeSnapshotRestorer,
             ThemedIconSnapshotRestorer themedIconSnapshotRestorer,
             ThemedIconInteractor themedIconInteractor) {
@@ -83,9 +78,8 @@
                 keyguardQuickAffordancePickerViewModelFactory;
         mNotificationSectionViewModelFactory = notificationSectionViewModelFactory;
         mFlags = flags;
-        mClockRegistryProvider = clockRegistryProvider;
-        mClockCarouselViewModelProvider = clockCarouselViewModelProvider;
-        mClockViewFactoryProvider = clockViewFactoryProvider;
+        mClockCarouselViewModel = clockCarouselViewModel;
+        mClockViewFactory = clockViewFactory;
         mDarkModeSnapshotRestorer = darkModeSnapshotRestorer;
         mThemedIconSnapshotRestorer = themedIconSnapshotRestorer;
         mThemedIconInteractor = themedIconInteractor;
@@ -116,9 +110,8 @@
                         wallpaperInfoFactory,
                         wallpaperColorsViewModel,
                         displayUtils,
-                        mClockRegistryProvider,
-                        mClockCarouselViewModelProvider,
-                        mClockViewFactoryProvider,
+                        mClockCarouselViewModel,
+                        mClockViewFactory,
                         sectionNavigationController)
                         : new ScreenPreviewSectionController(
                                 activity,
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index df92556..09466e3 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -52,8 +52,6 @@
 import com.android.customization.picker.notifications.domain.interactor.NotificationsInteractor
 import com.android.customization.picker.notifications.domain.interactor.NotificationsSnapshotRestorer
 import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel
-import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController.ClockCarouselViewModelProvider
-import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController.ClockViewFactoryProvider
 import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
@@ -93,7 +91,7 @@
     private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
         null
     private var notificationsSnapshotRestorer: NotificationsSnapshotRestorer? = null
-    private var clockRegistryProvider: ClockRegistryProvider? = null
+    private var clockRegistry: ClockRegistry? = null
     private var clockPickerInteractor: ClockPickerInteractor? = null
     private var clockSectionViewModel: ClockSectionViewModel? = null
     private var clockCarouselViewModel: ClockCarouselViewModel? = null
@@ -124,23 +122,8 @@
                         interactor = getNotificationsInteractor(activity),
                     ),
                     getFlags(),
-                    getClockRegistryProvider(activity),
-                    object : ClockCarouselViewModelProvider {
-                        override fun get(registry: ClockRegistry): ClockCarouselViewModel {
-                            return getClockCarouselViewModel(
-                                context = activity,
-                                clockRegistry = registry,
-                            )
-                        }
-                    },
-                    object : ClockViewFactoryProvider {
-                        override fun get(registry: ClockRegistry): ClockViewFactory {
-                            return getClockViewFactory(
-                                activity = activity,
-                                registry = registry,
-                            )
-                        }
-                    },
+                    getClockCarouselViewModel(activity),
+                    getClockViewFactory(activity),
                     getDarkModeSnapshotRestorer(activity),
                     getThemedIconSnapshotRestorer(activity),
                     getThemedIconInteractor(),
@@ -297,59 +280,49 @@
                 .also { notificationsSnapshotRestorer = it }
     }
 
-    override fun getClockRegistryProvider(context: Context): ClockRegistryProvider {
-        return clockRegistryProvider
+    override fun getClockRegistry(context: Context): ClockRegistry {
+        return clockRegistry
             ?: ClockRegistryProvider(
                     context = context,
                     coroutineScope = GlobalScope,
                     mainDispatcher = Dispatchers.Main,
                     backgroundDispatcher = Dispatchers.IO,
                 )
-                .also { clockRegistryProvider = it }
+                .get()
+                .also { clockRegistry = it }
     }
 
     override fun getClockPickerInteractor(
         context: Context,
-        clockRegistry: ClockRegistry,
     ): ClockPickerInteractor {
         return clockPickerInteractor
             ?: ClockPickerInteractor(
                     ClockPickerRepositoryImpl(
                         secureSettingsRepository = getSecureSettingsRepository(context),
-                        registry = clockRegistry,
+                        registry = getClockRegistry(context),
                         scope = GlobalScope,
-                        backgroundDispatcher = Dispatchers.IO,
                     ),
                 )
                 .also { clockPickerInteractor = it }
     }
 
-    override fun getClockSectionViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry,
-    ): ClockSectionViewModel {
+    override fun getClockSectionViewModel(context: Context): ClockSectionViewModel {
         return clockSectionViewModel
-            ?: ClockSectionViewModel(getClockPickerInteractor(context, clockRegistry)).also {
+            ?: ClockSectionViewModel(getClockPickerInteractor(context)).also {
                 clockSectionViewModel = it
             }
     }
 
-    override fun getClockCarouselViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry
-    ): ClockCarouselViewModel {
+    override fun getClockCarouselViewModel(context: Context): ClockCarouselViewModel {
         return clockCarouselViewModel
-            ?: ClockCarouselViewModel(getClockPickerInteractor(context, clockRegistry)).also {
+            ?: ClockCarouselViewModel(getClockPickerInteractor(context)).also {
                 clockCarouselViewModel = it
             }
     }
 
-    override fun getClockViewFactory(
-        activity: Activity,
-        registry: ClockRegistry,
-    ): ClockViewFactory {
+    override fun getClockViewFactory(activity: Activity): ClockViewFactory {
         return clockViewFactory
-            ?: ClockViewFactory(activity, registry).also { clockViewFactory = it }
+            ?: ClockViewFactory(activity, getClockRegistry(activity)).also { clockViewFactory = it }
     }
 
     protected fun getNotificationsInteractor(
@@ -426,12 +399,11 @@
 
     override fun getClockSettingsViewModelFactory(
         context: Context,
-        registry: ClockRegistry,
     ): ClockSettingsViewModel.Factory {
         return clockSettingsViewModelFactory
             ?: ClockSettingsViewModel.Factory(
                     context,
-                    getClockPickerInteractor(context, registry),
+                    getClockPickerInteractor(context),
                 )
                 .also { clockSettingsViewModelFactory = it }
     }
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 690b649..66793cd 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
@@ -25,7 +25,7 @@
  * clocks.
  */
 interface ClockPickerRepository {
-    val allClocks: Array<ClockMetadataModel>
+    val allClocks: Flow<List<ClockMetadataModel>>
 
     val selectedClock: Flow<ClockMetadataModel>
 
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 6c845f9..a360b6c 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -17,64 +17,84 @@
 package com.android.customization.picker.clock.data.repository
 
 import android.provider.Settings
-import android.util.Log
 import com.android.customization.picker.clock.shared.ClockSize
 import com.android.customization.picker.clock.shared.model.ClockMetadataModel
 import com.android.systemui.plugins.ClockMetadata
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.wallpaper.settings.data.repository.SecureSettingsRepository
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.mapNotNull
 import kotlinx.coroutines.flow.shareIn
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /** Implementation of [ClockPickerRepository], using [ClockRegistry]. */
 class ClockPickerRepositoryImpl(
     private val secureSettingsRepository: SecureSettingsRepository,
     private val registry: ClockRegistry,
-    private val scope: CoroutineScope,
-    private val backgroundDispatcher: CoroutineDispatcher,
+    scope: CoroutineScope,
 ) : ClockPickerRepository {
 
-    override val allClocks: Array<ClockMetadataModel> =
-        registry
-            .getClocks()
-            .filter { "NOT_IN_USE" !in it.clockId }
-            .map { it.toModel(null) }
-            .toTypedArray()
+    @OptIn(ExperimentalCoroutinesApi::class)
+    override val allClocks: Flow<List<ClockMetadataModel>> =
+        callbackFlow {
+                fun send() {
+                    val allClocks =
+                        registry
+                            .getClocks()
+                            .filter { "NOT_IN_USE" !in it.clockId }
+                            .map { it.toModel(null) }
+                    trySend(allClocks)
+                }
+
+                val listener =
+                    object : ClockRegistry.ClockChangeListener {
+                        override fun onAvailableClocksChanged() {
+                            send()
+                        }
+                    }
+                registry.registerClockChangeListener(listener)
+                send()
+                awaitClose { registry.unregisterClockChangeListener(listener) }
+            }
+            .mapLatest { allClocks ->
+                // Loading list of clock plugins can cause many consecutive calls of
+                // onAvailableClocksChanged(). We only care about the final fully-initiated clock
+                // list. Delay to avoid unnecessary too many emits.
+                delay(100)
+                allClocks
+            }
 
     /** The currently-selected clock. */
     override val selectedClock: Flow<ClockMetadataModel> =
         callbackFlow {
-                suspend fun send() {
-                    val currentClockId =
-                        withContext(backgroundDispatcher) { registry.currentClockId }
+                fun send() {
+                    val currentClockId = registry.currentClockId
+                    // It is possible that the model can be null since the full clock list is not
+                    // initiated.
                     val model =
                         registry
                             .getClocks()
                             .find { clockMetadata -> clockMetadata.clockId == currentClockId }
                             ?.toModel(registry.seedColor)
-                    if (model == null) {
-                        Log.w(
-                            TAG,
-                            "Clock with ID \"$currentClockId\" not found!",
-                        )
-                    }
                     trySend(model)
                 }
 
                 val listener =
                     object : ClockRegistry.ClockChangeListener {
                         override fun onCurrentClockChanged() {
-                            scope.launch { send() }
+                            send()
+                        }
+
+                        override fun onAvailableClocksChanged() {
+                            send()
                         }
                     }
                 registry.registerClockChangeListener(listener)
@@ -105,19 +125,13 @@
             )
 
     override suspend fun setClockSize(size: ClockSize) {
-        withContext(backgroundDispatcher) {
-            secureSettingsRepository.set(
-                name = Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
-                value = if (size == ClockSize.DYNAMIC) 1 else 0,
-            )
-        }
+        secureSettingsRepository.set(
+            name = Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
+            value = if (size == ClockSize.DYNAMIC) 1 else 0,
+        )
     }
 
     private fun ClockMetadata.toModel(color: Int?): ClockMetadataModel {
         return ClockMetadataModel(clockId = clockId, name = name, color = color)
     }
-
-    companion object {
-        private const val TAG = "ClockPickerRepositoryImpl"
-    }
 }
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt b/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
index f5001f0..bfe87c9 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockRegistryProvider.kt
@@ -19,9 +19,7 @@
 import android.content.ComponentName
 import android.content.Context
 import android.view.LayoutInflater
-import com.android.systemui.plugins.ClockProviderPlugin
 import com.android.systemui.plugins.Plugin
-import com.android.systemui.plugins.PluginListener
 import com.android.systemui.plugins.PluginManager
 import com.android.systemui.shared.clocks.ClockRegistry
 import com.android.systemui.shared.clocks.DefaultClockProvider
@@ -34,7 +32,6 @@
 import java.util.concurrent.Executors
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.suspendCancellableCoroutine
 
 /**
  * Provide the [ClockRegistry] singleton. Note that we need to make sure that the [PluginManager]
@@ -61,25 +58,8 @@
             .apply { registerListeners() }
     }
 
-    suspend fun get(): ClockRegistry {
-        return suspendCancellableCoroutine { continuation ->
-            val pluginListener =
-                object : PluginListener<ClockProviderPlugin> {
-                    var hasConnected = false
-                    override fun onPluginConnected(
-                        plugin: ClockProviderPlugin?,
-                        pluginContext: Context?
-                    ) {
-                        if (!hasConnected) {
-                            pluginManager.removePluginListener(this)
-                            hasConnected = true
-                            continuation.resumeWith(Result.success(clockRegistry))
-                        }
-                    }
-                }
-            pluginManager.addPluginListener(pluginListener, ClockProviderPlugin::class.java, true)
-            continuation.invokeOnCancellation { pluginManager.removePluginListener(pluginListener) }
-        }
+    fun get(): ClockRegistry {
+        return clockRegistry
     }
 
     private fun createPluginManager(context: Context): PluginManager {
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 c12778b..677fcfa 100644
--- a/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
+++ b/src/com/android/customization/picker/clock/domain/interactor/ClockPickerInteractor.kt
@@ -28,7 +28,8 @@
  * clocks.
  */
 class ClockPickerInteractor(private val repository: ClockPickerRepository) {
-    val allClocks: Array<ClockMetadataModel> = repository.allClocks
+
+    val allClocks: Flow<List<ClockMetadataModel>> = repository.allClocks
 
     val selectedClock: Flow<ClockMetadataModel> = repository.selectedClock
 
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 841c411..35a78cb 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockCarouselViewBinder.kt
@@ -23,6 +23,7 @@
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.customization.picker.clock.ui.view.ClockCarouselView
 import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
+import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 
 object ClockCarouselViewBinder {
@@ -42,14 +43,22 @@
         clockViewFactory: (clockId: String) -> View,
         lifecycleOwner: LifecycleOwner,
     ): Binding {
-        view.setUpImageCarouselView(
-            clockIds = viewModel.allClockIds,
-            onGetClockPreview = clockViewFactory,
-            onClockSelected = { clockId -> viewModel.setSelectedClock(clockId) }
-        )
         lifecycleOwner.lifecycleScope.launch {
             lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                launch { viewModel.selectedClockId.collect { view.setSelectedClockId(it) } }
+                launch {
+                    viewModel.allClockIds.collect { allClockIds ->
+                        view.setUpClockCarouselView(
+                            clockIds = allClockIds,
+                            onGetClockPreview = clockViewFactory,
+                            onClockSelected = { clockId -> viewModel.setSelectedClock(clockId) },
+                        )
+                    }
+                }
+                launch {
+                    viewModel.selectedIndex.collect { selectedIndex ->
+                        view.setSelectedClockIndex(selectedIndex)
+                    }
+                }
             }
         }
         return object : Binding {
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockCarouselDemoFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockCarouselDemoFragment.kt
deleted file mode 100644
index a4b1c1e..0000000
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockCarouselDemoFragment.kt
+++ /dev/null
@@ -1,69 +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.ui.fragment
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.lifecycle.lifecycleScope
-import com.android.customization.module.ThemePickerInjector
-import com.android.customization.picker.clock.ui.binder.ClockCarouselViewBinder
-import com.android.customization.picker.clock.ui.view.ClockCarouselView
-import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
-import com.android.wallpaper.R
-import com.android.wallpaper.module.InjectorProvider
-import com.android.wallpaper.picker.AppbarFragment
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-
-class ClockCarouselDemoFragment : AppbarFragment() {
-
-    override fun onCreateView(
-        inflater: LayoutInflater,
-        container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View {
-        val injector = InjectorProvider.getInjector() as ThemePickerInjector
-        val view = inflater.inflate(R.layout.fragment_clock_carousel_demo, container, false)
-        setUpToolbar(view)
-        val carouselView = view.requireViewById<ClockCarouselView>(R.id.image_carousel_view)
-        lifecycleScope.launch {
-            val registry =
-                withContext(Dispatchers.IO) {
-                    injector.getClockRegistryProvider(requireContext()).get()
-                }
-            ClockCarouselViewBinder.bind(
-                view = carouselView,
-                viewModel =
-                    ClockCarouselViewModel(
-                        injector.getClockPickerInteractor(requireContext(), registry)
-                    ),
-                clockViewFactory = { clockId ->
-                    registry.createExampleClock(clockId)?.largeClock?.view!!
-                },
-                lifecycleOwner = this@ClockCarouselDemoFragment,
-            )
-        }
-
-        return view
-    }
-
-    override fun getDefaultTitle(): CharSequence {
-        return "Clock H-scroll Demo"
-    }
-}
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt b/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
index 4aa5de4..7e53ac4 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockCustomDemoFragment.kt
@@ -13,7 +13,6 @@
 import android.widget.TextView
 import android.widget.Toast
 import androidx.core.view.setPadding
-import androidx.lifecycle.lifecycleScope
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.android.customization.module.ThemePickerInjector
@@ -23,9 +22,6 @@
 import com.android.wallpaper.R
 import com.android.wallpaper.module.InjectorProvider
 import com.android.wallpaper.picker.AppbarFragment
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 class ClockCustomDemoFragment : AppbarFragment() {
     @VisibleForTesting lateinit var recyclerView: RecyclerView
@@ -38,27 +34,20 @@
     ): View {
         val view = inflater.inflate(R.layout.fragment_clock_custom_picker_demo, container, false)
         setUpToolbar(view)
-        lifecycleScope.launch {
-            clockRegistry =
-                withContext(Dispatchers.IO) {
-                    (InjectorProvider.getInjector() as ThemePickerInjector)
-                        .getClockRegistryProvider(requireContext())
-                        .get()
-                }
-            val listInUse = clockRegistry.getClocks().filter { "NOT_IN_USE" !in it.clockId }
-            recyclerView.adapter =
-                ClockRecyclerAdapter(listInUse, requireContext()) {
-                    clockRegistry.currentClockId = it.clockId
-                    Toast.makeText(context, "${it.name} selected", Toast.LENGTH_SHORT).show()
-                }
-        }
-        return view
-    }
+        clockRegistry =
+            (InjectorProvider.getInjector() as ThemePickerInjector).getClockRegistry(
+                requireContext()
+            )
+        val listInUse = clockRegistry.getClocks().filter { "NOT_IN_USE" !in it.clockId }
 
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         recyclerView = view.requireViewById(R.id.clock_preview_card_list_demo)
         recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
-        super.onViewCreated(view, savedInstanceState)
+        recyclerView.adapter =
+            ClockRecyclerAdapter(listInUse, requireContext()) {
+                clockRegistry.currentClockId = it.clockId
+                Toast.makeText(context, "${it.name} selected", Toast.LENGTH_SHORT).show()
+            }
+        return view
     }
 
     override fun getDefaultTitle(): CharSequence {
diff --git a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomFragment.java b/src/com/android/customization/picker/clock/ui/fragment/ClockCustomFragment.java
deleted file mode 100644
index ea267ab..0000000
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockCustomFragment.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2022 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.fragment;
-
-import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY;
-import static com.android.wallpaper.widget.BottomActionBar.BottomAction.INFORMATION;
-
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.customization.model.clock.custom.ClockCustomManager;
-import com.android.customization.model.clock.custom.ClockOption;
-import com.android.customization.widget.OptionSelectorController;
-import com.android.wallpaper.R;
-import com.android.wallpaper.picker.AppbarFragment;
-import com.android.wallpaper.widget.BottomActionBar;
-
-import com.google.common.collect.Lists;
-
-/**
- * Fragment that contains the main UI for selecting and applying a custom clock.
- */
-public class ClockCustomFragment extends AppbarFragment {
-
-    OptionSelectorController<ClockOption> mClockSelectorController;
-
-    @Nullable
-    @Override
-    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
-            @Nullable Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.fragment_clock_custom_picker, container, false);
-
-        setUpToolbar(view);
-
-        RecyclerView clockPreviewCardList = view.requireViewById(R.id.clock_preview_card_list);
-
-        mClockSelectorController = new OptionSelectorController<>(clockPreviewCardList,
-                Lists.newArrayList(new ClockOption(), new ClockOption(), new ClockOption(),
-                        new ClockOption(), new ClockOption()), false,
-                OptionSelectorController.CheckmarkStyle.CENTER_CHANGE_COLOR_WHEN_NOT_SELECTED);
-        mClockSelectorController.initOptions(new ClockCustomManager());
-
-        return view;
-    }
-
-    @Override
-    public CharSequence getDefaultTitle() {
-        return getString(R.string.clock_title);
-    }
-
-    @Override
-    protected void onBottomActionBarReady(BottomActionBar bottomActionBar) {
-        super.onBottomActionBarReady(bottomActionBar);
-        bottomActionBar.showActionsOnly(INFORMATION, APPLY);
-        bottomActionBar.show();
-    }
-}
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 12cef39..976907b 100644
--- a/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
+++ b/src/com/android/customization/picker/clock/ui/fragment/ClockSettingsFragment.kt
@@ -22,7 +22,6 @@
 import androidx.cardview.widget.CardView
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.get
-import androidx.lifecycle.lifecycleScope
 import com.android.customization.module.ThemePickerInjector
 import com.android.customization.picker.clock.ui.binder.ClockSettingsBinder
 import com.android.wallpaper.R
@@ -32,11 +31,8 @@
 import com.android.wallpaper.picker.customization.ui.binder.ScreenPreviewBinder
 import com.android.wallpaper.picker.customization.ui.viewmodel.ScreenPreviewViewModel
 import com.android.wallpaper.util.PreviewUtils
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlinx.coroutines.withContext
 
 @OptIn(ExperimentalCoroutinesApi::class)
 class ClockSettingsFragment : AppbarFragment() {
@@ -106,22 +102,15 @@
             )
             .show()
 
-        lifecycleScope.launch {
-            val registry =
-                withContext(Dispatchers.IO) { injector.getClockRegistryProvider(context).get() }
-            ClockSettingsBinder.bind(
-                view,
-                ViewModelProvider(
-                        requireActivity(),
-                        injector.getClockSettingsViewModelFactory(
-                            context = context,
-                            registry = registry,
-                        ),
-                    )
-                    .get(),
-                this@ClockSettingsFragment,
-            )
-        }
+        ClockSettingsBinder.bind(
+            view,
+            ViewModelProvider(
+                    requireActivity(),
+                    injector.getClockSettingsViewModelFactory(context),
+                )
+                .get(),
+            this@ClockSettingsFragment,
+        )
 
         return view
     }
diff --git a/src/com/android/customization/picker/clock/ui/section/ClockSectionController.kt b/src/com/android/customization/picker/clock/ui/section/ClockSectionController.kt
index e1982d7..c50fe98 100644
--- a/src/com/android/customization/picker/clock/ui/section/ClockSectionController.kt
+++ b/src/com/android/customization/picker/clock/ui/section/ClockSectionController.kt
@@ -19,26 +19,22 @@
 import android.view.LayoutInflater
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
-import com.android.customization.module.ThemePickerInjector
-import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
 import com.android.customization.picker.clock.ui.binder.ClockSectionViewBinder
 import com.android.customization.picker.clock.ui.fragment.ClockSettingsFragment
 import com.android.customization.picker.clock.ui.view.ClockSectionView
+import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 import com.android.wallpaper.R
 import com.android.wallpaper.config.BaseFlags
 import com.android.wallpaper.model.CustomizationSectionController
 import com.android.wallpaper.model.CustomizationSectionController.CustomizationSectionNavigationController
-import com.android.wallpaper.module.InjectorProvider
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /** A [CustomizationSectionController] for clock customization. */
 class ClockSectionController(
     private val navigationController: CustomizationSectionNavigationController,
     private val lifecycleOwner: LifecycleOwner,
     private val flag: BaseFlags,
-    private val clockRegistryProvider: ClockRegistryProvider,
+    private val viewModel: ClockSectionViewModel,
 ) : CustomizationSectionController<ClockSectionView> {
 
     override fun isAvailable(context: Context): Boolean {
@@ -53,12 +49,9 @@
                     null,
                 ) as ClockSectionView
         lifecycleOwner.lifecycleScope.launch {
-            val registry = withContext(Dispatchers.IO) { clockRegistryProvider.get() }
             ClockSectionViewBinder.bind(
                 view = view,
-                viewModel =
-                    (InjectorProvider.getInjector() as ThemePickerInjector)
-                        .getClockSectionViewModel(context, registry),
+                viewModel = viewModel,
                 lifecycleOwner = lifecycleOwner
             ) { navigationController.navigateTo(ClockSettingsFragment()) }
         }
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 e16492f..90d7c42 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -42,23 +42,24 @@
         carousel = view.requireViewById(R.id.carousel)
     }
 
-    fun setUpImageCarouselView(
-        clockIds: Array<String>,
+    fun setUpClockCarouselView(
+        clockIds: List<String>,
         onGetClockPreview: (clockId: String) -> View,
         onClockSelected: (clockId: String) -> Unit,
     ) {
         adapter = ClockCarouselAdapter(clockIds, onGetClockPreview, onClockSelected)
         carousel.setAdapter(adapter)
+        carousel.refresh()
     }
 
-    fun setSelectedClockId(
-        selectedClockId: String,
+    fun setSelectedClockIndex(
+        index: Int,
     ) {
-        carousel.jumpToIndex(adapter.clockIds.indexOf(selectedClockId))
+        carousel.jumpToIndex(index)
     }
 
     class ClockCarouselAdapter(
-        val clockIds: Array<String>,
+        val clockIds: List<String>,
         val onGetClockPreview: (clockId: String) -> View,
         val onClockSelected: (clockId: String) -> Unit,
     ) : Carousel.Adapter {
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 b126a73..751661f 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -16,15 +16,46 @@
 package com.android.customization.picker.clock.ui.viewmodel
 
 import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.mapNotNull
 
-class ClockCarouselViewModel(private val interactor: ClockPickerInteractor) {
-    val selectedClockId: Flow<String> = interactor.selectedClock.map { it.clockId }
+class ClockCarouselViewModel(
+    private val interactor: ClockPickerInteractor,
+) {
 
-    val allClockIds: Array<String> = interactor.allClocks.map { it.clockId }.toTypedArray()
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val allClockIds: Flow<List<String>> =
+        interactor.allClocks.mapLatest { clockArray ->
+            // Delay to avoid the case that the full list of clocks is not initiated.
+            delay(CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
+            clockArray.map { it.clockId }
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val selectedIndex: Flow<Int> =
+        allClockIds
+            .flatMapLatest { allClockIds ->
+                interactor.selectedClock.map { selectedClock ->
+                    val index = allClockIds.indexOf(selectedClock.clockId)
+                    if (index >= 0) {
+                        index
+                    } else {
+                        null
+                    }
+                }
+            }
+            .mapNotNull { it }
 
     fun setSelectedClock(clockId: String) {
         interactor.setSelectedClock(clockId)
     }
+
+    companion object {
+        const val CLOCKS_EVENT_UPDATE_DELAY_MILLIS: Long = 100
+    }
 }
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 1ffb7b8..c15bc67 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockSettingsViewModel.kt
@@ -232,7 +232,7 @@
                 arrayOf(144f, 0.65f, 0.74f).toFloatArray(),
             )
 
-        val COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS: Long = 100
+        const val COLOR_OPTIONS_EVENT_UPDATE_DELAY_MILLIS: Long = 100
 
         fun getSelectedColorPosition(selectedColorHsl: FloatArray): Int {
             return COLOR_LIST_HSL.withIndex().minBy { abs(it.value[0] - selectedColorHsl[0]) }.index
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 9a31ae9..f7fa9a5 100644
--- a/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
+++ b/src/com/android/customization/picker/preview/ui/section/PreviewWithClockCarouselSectionController.kt
@@ -23,12 +23,10 @@
 import androidx.core.view.isGone
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
-import com.android.customization.picker.clock.data.repository.ClockRegistryProvider
 import com.android.customization.picker.clock.ui.binder.ClockCarouselViewBinder
 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.systemui.shared.clocks.ClockRegistry
 import com.android.wallpaper.R
 import com.android.wallpaper.model.CustomizationSectionController
 import com.android.wallpaper.model.WallpaperColorsViewModel
@@ -37,13 +35,9 @@
 import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewSectionController
 import com.android.wallpaper.picker.customization.ui.section.ScreenPreviewView
 import com.android.wallpaper.util.DisplayUtils
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /** Controls the screen preview section. */
-@OptIn(ExperimentalCoroutinesApi::class)
 class PreviewWithClockCarouselSectionController(
     activity: Activity,
     private val lifecycleOwner: LifecycleOwner,
@@ -51,9 +45,8 @@
     wallpaperInfoFactory: CurrentWallpaperInfoFactory,
     colorViewModel: WallpaperColorsViewModel,
     displayUtils: DisplayUtils,
-    private val clockRegistryProvider: ClockRegistryProvider,
-    private val clockCarouselViewModelProvider: ClockCarouselViewModelProvider,
-    private val clockViewFactoryProvider: ClockViewFactoryProvider,
+    private val clockCarouselViewModel: ClockCarouselViewModel,
+    private val clockViewFactory: ClockViewFactory,
     navigator: CustomizationSectionController.CustomizationSectionNavigationController,
 ) :
     ScreenPreviewSectionController(
@@ -77,12 +70,10 @@
         val carouselView: ClockCarouselView = carouselViewStub.inflate() as ClockCarouselView
         carouselView.isGone = true
         lifecycleOwner.lifecycleScope.launch {
-            val registry = withContext(Dispatchers.IO) { clockRegistryProvider.get() }
-            val clockViewFactory = clockViewFactoryProvider.get(registry)
             clockCarouselBinding =
                 ClockCarouselViewBinder.bind(
                     view = carouselView,
-                    viewModel = clockCarouselViewModelProvider.get(registry),
+                    viewModel = clockCarouselViewModel,
                     clockViewFactory = { clockId -> clockViewFactory.getView(clockId) },
                     lifecycleOwner = lifecycleOwner,
                 )
@@ -101,12 +92,4 @@
             clockCarouselBinding?.hide()
         }
     }
-
-    interface ClockCarouselViewModelProvider {
-        fun get(registry: ClockRegistry): ClockCarouselViewModel
-    }
-
-    interface ClockViewFactoryProvider {
-        fun get(registry: ClockRegistry): ClockViewFactory
-    }
 }
diff --git a/tests/src/com/android/customization/model/grid/ui/viewmodel/GridScreenViewModelTest.kt b/tests/src/com/android/customization/model/grid/ui/viewmodel/GridScreenViewModelTest.kt
index 951638a..7d0a527 100644
--- a/tests/src/com/android/customization/model/grid/ui/viewmodel/GridScreenViewModelTest.kt
+++ b/tests/src/com/android/customization/model/grid/ui/viewmodel/GridScreenViewModelTest.kt
@@ -31,6 +31,7 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -73,6 +74,7 @@
     }
 
     @Test
+    @Ignore("b/270371382")
     fun clickOnItem_itGetsSelected() =
         testScope.runTest {
             val optionItemsValueProvider = collectLastValue(underTest.optionItems)
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 1614c61..d2a9efc 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
@@ -23,14 +23,14 @@
 import kotlinx.coroutines.flow.combine
 
 class FakeClockPickerRepository : ClockPickerRepository {
+    override val allClocks: Flow<List<ClockMetadataModel>> =
+        MutableStateFlow(fakeClocks).asStateFlow()
 
-    override val allClocks: Array<ClockMetadataModel> = fakeClocks
-
-    private val _selectedClockId = MutableStateFlow(fakeClocks[0].clockId)
-    private val _clockColor = MutableStateFlow<Int?>(null)
+    private val selectedClockId = MutableStateFlow(fakeClocks[0].clockId)
+    private val clockColor = MutableStateFlow<Int?>(null)
     override val selectedClock: Flow<ClockMetadataModel> =
-        combine(_selectedClockId, _clockColor) { selectedClockId, clockColor ->
-            val selectedClock = allClocks.find { clock -> clock.clockId == selectedClockId }
+        combine(selectedClockId, clockColor) { selectedClockId, clockColor ->
+            val selectedClock = fakeClocks.find { clock -> clock.clockId == selectedClockId }
             checkNotNull(selectedClock)
             ClockMetadataModel(selectedClock.clockId, selectedClock.name, clockColor)
         }
@@ -39,11 +39,11 @@
     override val selectedClockSize: Flow<ClockSize> = _selectedClockSize.asStateFlow()
 
     override fun setSelectedClock(clockId: String) {
-        _selectedClockId.value = clockId
+        selectedClockId.value = clockId
     }
 
     override fun setClockColor(color: Int?) {
-        _clockColor.value = color
+        clockColor.value = color
     }
 
     override suspend fun setClockSize(size: ClockSize) {
@@ -52,7 +52,7 @@
 
     companion object {
         val fakeClocks =
-            arrayOf(
+            listOf(
                 ClockMetadataModel("clock0", "clock0", null),
                 ClockMetadataModel("clock1", "clock1", null),
                 ClockMetadataModel("clock2", "clock2", null),
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 776663e..8d7ec30 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
@@ -23,6 +23,7 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.resetMain
 import kotlinx.coroutines.test.runTest
 import kotlinx.coroutines.test.setMain
@@ -53,10 +54,9 @@
 
     @Test
     fun setSelectedClock() = runTest {
-        val observedSelectedClock = collectLastValue(underTest.selectedClockId)
-
+        val observedSelectedIndex = collectLastValue(underTest.selectedIndex)
+        advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
         underTest.setSelectedClock(FakeClockPickerRepository.fakeClocks[2].clockId)
-        assertThat(observedSelectedClock())
-            .isEqualTo(FakeClockPickerRepository.fakeClocks[2].clockId)
+        assertThat(observedSelectedIndex()).isEqualTo(2)
     }
 }
diff --git a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
index 0aac5cc..3ab7c84 100644
--- a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -48,7 +48,7 @@
     private var customizationProviderClient: CustomizationProviderClient? = null
     private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
         null
-    private var clockRegistryProvider: ClockRegistryProvider? = null
+    private var clockRegistry: ClockRegistry? = null
     private var clockPickerInteractor: ClockPickerInteractor? = null
     private var clockSectionViewModel: ClockSectionViewModel? = null
     private var clockViewFactory: ClockViewFactory? = null
@@ -142,29 +142,23 @@
                 .also { keyguardQuickAffordanceSnapshotRestorer = it }
     }
 
-    override fun getClockRegistryProvider(context: Context): ClockRegistryProvider {
-        return clockRegistryProvider
-            ?: ClockRegistryProvider(context, GlobalScope, Dispatchers.Main, Dispatchers.IO).also {
-                clockRegistryProvider = it
-            }
+    override fun getClockRegistry(context: Context): ClockRegistry {
+        return clockRegistry
+            ?: ClockRegistryProvider(context, GlobalScope, Dispatchers.Main, Dispatchers.IO)
+                .get()
+                .also { clockRegistry = it }
     }
 
-    override fun getClockPickerInteractor(
-        context: Context,
-        clockRegistry: ClockRegistry
-    ): ClockPickerInteractor {
+    override fun getClockPickerInteractor(context: Context): ClockPickerInteractor {
         return clockPickerInteractor
             ?: ClockPickerInteractor(FakeClockPickerRepository()).also {
                 clockPickerInteractor = it
             }
     }
 
-    override fun getClockSectionViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry
-    ): ClockSectionViewModel {
+    override fun getClockSectionViewModel(context: Context): ClockSectionViewModel {
         return clockSectionViewModel
-            ?: ClockSectionViewModel(getClockPickerInteractor(context, clockRegistry)).also {
+            ?: ClockSectionViewModel(getClockPickerInteractor(context)).also {
                 clockSectionViewModel = it
             }
     }
@@ -190,32 +184,25 @@
                 .also { colorPickerViewModelFactory = it }
     }
 
-    override fun getClockCarouselViewModel(
-        context: Context,
-        clockRegistry: ClockRegistry
-    ): ClockCarouselViewModel {
+    override fun getClockCarouselViewModel(context: Context): ClockCarouselViewModel {
         return clockCarouselViewModel
-            ?: ClockCarouselViewModel(getClockPickerInteractor(context, clockRegistry)).also {
+            ?: ClockCarouselViewModel(getClockPickerInteractor(context)).also {
                 clockCarouselViewModel = it
             }
     }
 
-    override fun getClockViewFactory(
-        activity: Activity,
-        registry: ClockRegistry
-    ): ClockViewFactory {
+    override fun getClockViewFactory(activity: Activity): ClockViewFactory {
         return clockViewFactory
-            ?: ClockViewFactory(activity, registry).also { clockViewFactory = it }
+            ?: ClockViewFactory(activity, getClockRegistry(activity)).also { clockViewFactory = it }
     }
 
     override fun getClockSettingsViewModelFactory(
         context: Context,
-        registry: ClockRegistry
     ): ClockSettingsViewModel.Factory {
         return clockSettingsViewModelFactory
             ?: ClockSettingsViewModel.Factory(
                     context,
-                    getClockPickerInteractor(context, registry),
+                    getClockPickerInteractor(context),
                 )
                 .also { clockSettingsViewModelFactory = it }
     }