[TP] Fix b/265245824 Avoid creation of ClockRegistry when not needed

We have permission issue creatring ClockRegistry for people who are not
eligible for custom clocks.
We avoid creating the ClockSectionViewmodel, and ClockRegistry to avoid
the unexpected permission issue.

Test: Manually tested that there is no crash
Bug: 265245824
Change-Id: I09cdaea786f44b9ed6a439319384375f071a8808
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 2772e56..f5d6c54 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -20,6 +20,7 @@
 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.ui.viewmodel.ClockSectionViewModel
 import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
 import com.android.systemui.plugins.PluginManager
 import com.android.systemui.shared.clocks.ClockRegistry
@@ -41,5 +42,7 @@
 
     fun getClockRegistry(context: Context): ClockRegistry
 
+    fun getClockSectionViewModel(context: Context): ClockSectionViewModel
+
     fun getPluginManager(context: Context): PluginManager
 }
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index b448283..5239b75 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -30,6 +30,9 @@
 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.ClockPickerRepositoryImpl
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 import com.android.customization.picker.notifications.data.repository.NotificationsRepository
 import com.android.customization.picker.notifications.domain.interactor.NotificationsInteractor
 import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel
@@ -79,6 +82,7 @@
     private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
         null
     private var clockRegistry: ClockRegistry? = null
+    private var clockSectionViewModel: ClockSectionViewModel? = null
     private var pluginManager: PluginManager? = null
     private var notificationsInteractor: NotificationsInteractor? = null
     private var notificationSectionViewModelFactory: NotificationSectionViewModel.Factory? = null
@@ -243,6 +247,14 @@
                 .also { clockRegistry = it }
     }
 
+    override fun getClockSectionViewModel(context: Context): ClockSectionViewModel {
+        return clockSectionViewModel
+            ?: ClockSectionViewModel(
+                    ClockPickerInteractor(ClockPickerRepositoryImpl(getClockRegistry(context)))
+                )
+                .also { clockSectionViewModel = it }
+    }
+
     override fun getPluginManager(context: Context): PluginManager {
         return pluginManager ?: createPluginManager(context).also { pluginManager = 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 52c2430..f160a3d 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepository.kt
@@ -14,48 +14,15 @@
  * limitations under the License.
  *
  */
-
 package com.android.customization.picker.clock.data.repository
 
-import android.util.Log
 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.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.callbackFlow
 
 /**
  * Repository for accessing application clock settings, as well as selecting and configuring custom
  * clocks.
  */
-class ClockPickerRepository(registry: ClockRegistry) {
-
-    /** The currently-selected clock. */
-    val selectedClock: Flow<ClockMetadataModel?> = callbackFlow {
-        fun send() {
-            val model =
-                registry
-                    .getClocks()
-                    .find { clockMetadata -> clockMetadata.clockId == registry.currentClockId }
-                    ?.toModel()
-            if (model == null) {
-                Log.e(TAG, "Currently selected clock ID is not one of the available clocks.")
-            }
-            trySend(model)
-        }
-
-        val listener = ClockRegistry.ClockChangeListener { send() }
-        registry.registerClockChangeListener(listener)
-        send()
-        awaitClose { registry.unregisterClockChangeListener(listener) }
-    }
-
-    private fun ClockMetadata.toModel(): ClockMetadataModel {
-        return ClockMetadataModel(clockId = clockId, name = name)
-    }
-
-    companion object {
-        private const val TAG = "ClockPickerRepository"
-    }
+interface ClockPickerRepository {
+    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
new file mode 100644
index 0000000..c307ca6
--- /dev/null
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.data.repository
+
+import android.util.Log
+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.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+
+/** Implementation of [ClockPickerRepository], using [ClockRegistry]. */
+class ClockPickerRepositoryImpl(registry: ClockRegistry) : ClockPickerRepository {
+
+    /** The currently-selected clock. */
+    override val selectedClock: Flow<ClockMetadataModel?> = callbackFlow {
+        fun send() {
+            val model =
+                registry
+                    .getClocks()
+                    .find { clockMetadata -> clockMetadata.clockId == registry.currentClockId }
+                    ?.toModel()
+            if (model == null) {
+                Log.e(TAG, "Currently selected clock ID is not one of the available clocks.")
+            }
+            trySend(model)
+        }
+
+        val listener = ClockRegistry.ClockChangeListener { send() }
+        registry.registerClockChangeListener(listener)
+        send()
+        awaitClose { registry.unregisterClockChangeListener(listener) }
+    }
+
+    private fun ClockMetadata.toModel(): ClockMetadataModel {
+        return ClockMetadataModel(clockId = clockId, name = name)
+    }
+
+    companion object {
+        private const val TAG = "ClockPickerRepositoryImpl"
+    }
+}
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
new file mode 100644
index 0000000..ea97c9a
--- /dev/null
+++ b/tests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.data.repository
+
+import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeClockPickerRepository : ClockPickerRepository {
+
+    override val selectedClock: Flow<ClockMetadataModel?> = MutableStateFlow(null)
+}
diff --git a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
index afc7131..eb135d9 100644
--- a/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -11,6 +11,9 @@
 import com.android.customization.module.CustomizationInjector
 import com.android.customization.module.CustomizationPreferences
 import com.android.customization.module.ThemesUserEventLogger
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
+import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
 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
@@ -25,7 +28,6 @@
 import com.android.wallpaper.module.UserEventLogger
 import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
 import com.android.wallpaper.testing.TestInjector
-import java.util.HashMap
 import kotlinx.coroutines.Dispatchers.IO
 
 /** Test implementation of the dependency injector. */
@@ -42,6 +44,7 @@
     private var keyguardQuickAffordanceSnapshotRestorer: KeyguardQuickAffordanceSnapshotRestorer? =
         null
     private var clockRegistry: ClockRegistry? = null
+    private var clockSectionViewModel: ClockSectionViewModel? = null
     private var pluginManager: PluginManager? = null
 
     override fun getCustomizationPreferences(context: Context): CustomizationPreferences {
@@ -141,6 +144,13 @@
                 .also { clockRegistry = it }
     }
 
+    override fun getClockSectionViewModel(context: Context): ClockSectionViewModel {
+        return clockSectionViewModel
+            ?: ClockSectionViewModel(ClockPickerInteractor(FakeClockPickerRepository())).also {
+                clockSectionViewModel = it
+            }
+    }
+
     override fun getPluginManager(context: Context): PluginManager {
         return pluginManager ?: TestPluginManager().also { pluginManager = it }
     }