Fixes instant crash in WPP.

Turns out that getClocks() can return a collection that has no clock
that matches the ID returned from getCurrentClockId().

Also, getCurrentClockId() is accessing Settings (which is a content
provider) on the main thread. A separate bug has been filed to fix that
in the ClockRegistry. This CL offers a workaround of moving the
expensive call to the background and for doing it only once instead of
up to N times each time.

Fix: 267356108
Test: WPP no longer crashes. Clocks screen shows the textual list of clocks.
Change-Id: I91eb54697feea53db89f297b7fa2d045028246ae
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index 581c233..c958123 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -235,9 +235,14 @@
         clockRegistry: ClockRegistry,
     ): ClockPickerInteractor {
         return clockPickerInteractor
-            ?: ClockPickerInteractor(ClockPickerRepositoryImpl(clockRegistry)).also {
-                clockPickerInteractor = it
-            }
+            ?: ClockPickerInteractor(
+                    ClockPickerRepositoryImpl(
+                        registry = clockRegistry,
+                        scope = GlobalScope,
+                        backgroundDispatcher = Dispatchers.IO,
+                    )
+                )
+                .also { clockPickerInteractor = it }
     }
 
     override fun getClockSectionViewModel(
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 d5830e2..f6b0514 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -16,18 +16,28 @@
  */
 package com.android.customization.picker.clock.data.repository
 
+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 kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 /** Implementation of [ClockPickerRepository], using [ClockRegistry]. */
-class ClockPickerRepositoryImpl(private val registry: ClockRegistry) : ClockPickerRepository {
+class ClockPickerRepositoryImpl(
+    private val registry: ClockRegistry,
+    private val scope: CoroutineScope,
+    private val backgroundDispatcher: CoroutineDispatcher,
+) : ClockPickerRepository {
 
     override val allClocks: Array<ClockMetadataModel> =
         registry
@@ -37,22 +47,31 @@
             .toTypedArray()
 
     /** The currently-selected clock. */
-    override val selectedClock: Flow<ClockMetadataModel> = callbackFlow {
-        fun send() {
-            val model =
-                registry
-                    .getClocks()
-                    .find { clockMetadata -> clockMetadata.clockId == registry.currentClockId }
-                    ?.toModel()
-            checkNotNull(model)
-            trySend(model)
-        }
+    override val selectedClock: Flow<ClockMetadataModel> =
+        callbackFlow {
+                suspend fun send() {
+                    val currentClockId =
+                        withContext(backgroundDispatcher) { registry.currentClockId }
+                    val model =
+                        registry
+                            .getClocks()
+                            .find { clockMetadata -> clockMetadata.clockId == currentClockId }
+                            ?.toModel()
+                    if (model == null) {
+                        Log.w(
+                            TAG,
+                            "Clock with ID \"$currentClockId\" not found!",
+                        )
+                    }
+                    trySend(model)
+                }
 
-        val listener = ClockRegistry.ClockChangeListener { send() }
-        registry.registerClockChangeListener(listener)
-        send()
-        awaitClose { registry.unregisterClockChangeListener(listener) }
-    }
+                val listener = ClockRegistry.ClockChangeListener { scope.launch { send() } }
+                registry.registerClockChangeListener(listener)
+                send()
+                awaitClose { registry.unregisterClockChangeListener(listener) }
+            }
+            .mapNotNull { it }
 
     override fun setSelectedClock(clockId: String) {
         registry.currentClockId = clockId
@@ -69,4 +88,8 @@
     private fun ClockMetadata.toModel(): ClockMetadataModel {
         return ClockMetadataModel(clockId = clockId, name = name)
     }
+
+    companion object {
+        private const val TAG = "ClockPickerRepositoryImpl"
+    }
 }