Setting for Lockscreen Clock

Bug: 229771520
Test: Automated
Change-Id: Ia5b4dfe38d48a41cbfb59109c819647b9e8398cf
(cherry picked from commit e3004a6e5f2e8ef2e70df41bf965ed9be7b1675e)
Merged-In: Ia5b4dfe38d48a41cbfb59109c819647b9e8398cf
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 9f790c6..114ea65 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -50,6 +50,7 @@
         "SystemUIUnfoldLib",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx.concurrent_concurrent-futures",
+        "gson-prebuilt-jar",
         "dagger2",
         "jsr330",
     ],
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 209b576..3245966 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -14,24 +14,42 @@
 package com.android.systemui.shared.clocks
 
 import android.content.Context
+import android.database.ContentObserver
 import android.graphics.drawable.Drawable
+import android.net.Uri
+import android.os.Handler
+import android.os.UserHandle
+import android.provider.Settings
 import android.util.Log
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.PluginListener
 import com.android.systemui.shared.plugins.PluginManager
+import com.google.gson.Gson
 import javax.inject.Inject
 
 private val TAG = ClockRegistry::class.simpleName
-private const val DEFAULT_CLOCK_ID = "DEFAULT"
+private val DEBUG = true
+const val DEFAULT_CLOCK_ID = "DEFAULT"
 
 typealias ClockChangeListener = () -> Unit
 
 /** ClockRegistry aggregates providers and plugins */
-class ClockRegistry @Inject constructor(
+open class ClockRegistry @Inject constructor(
     val context: Context,
-    val pluginManager: PluginManager
+    val pluginManager: PluginManager,
+    @Main val handler: Handler
 ) {
-    val pluginListener = object : PluginListener<ClockProviderPlugin> {
+    private val gson = Gson()
+    private val availableClocks = mutableMapOf<ClockId, ClockInfo>()
+    private val clockChangeListeners = mutableListOf<ClockChangeListener>()
+    private val settingObserver = object : ContentObserver(handler) {
+        override fun onChange(selfChange: Boolean, uris: Collection<Uri>, flags: Int, userId: Int) =
+            clockChangeListeners.forEach { it() }
+    }
+
+    private val pluginListener = object : PluginListener<ClockProviderPlugin> {
         override fun onPluginConnected(plugin: ClockProviderPlugin, context: Context) {
+            val currentId = currentClockId
             for (clock in plugin.getClocks()) {
                 val id = clock.clockId
                 val current = availableClocks[id]
@@ -42,21 +60,48 @@
                 }
 
                 availableClocks[id] = ClockInfo(clock, plugin)
+
+                if (currentId == id) {
+                    if (DEBUG) {
+                        Log.i(TAG, "Current clock ($currentId) was connected")
+                    }
+                    clockChangeListeners.forEach { it() }
+                }
             }
         }
 
         override fun onPluginDisconnected(plugin: ClockProviderPlugin) {
+            val currentId = currentClockId
             for (clock in plugin.getClocks()) {
                 availableClocks.remove(clock.clockId)
+
+                if (currentId == clock.clockId) {
+                    Log.w(TAG, "Current clock ($currentId) was disconnected")
+                    clockChangeListeners.forEach { it() }
+                }
             }
         }
     }
 
-    private val availableClocks = mutableMapOf<ClockId, ClockInfo>()
+    open var currentClockId: ClockId
+        get() {
+            val json = Settings.Secure.getString(context.contentResolver,
+                Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE)
+            return gson.fromJson(json, ClockSetting::class.java).clockId
+        }
+        set(value) {
+            val json = gson.toJson(ClockSetting(value, System.currentTimeMillis()))
+            Settings.Secure.putString(context.contentResolver,
+                Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, json)
+        }
 
     init {
         pluginManager.addPluginListener(pluginListener, ClockProviderPlugin::class.java)
-        // TODO: Register Settings ContentObserver
+        context.contentResolver.registerContentObserver(
+            Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
+            false,
+            settingObserver,
+            UserHandle.USER_ALL)
     }
 
     fun getClocks(): List<ClockMetadata> = availableClocks.map { (_, clock) -> clock.metadata }
@@ -66,8 +111,14 @@
 
     fun createExampleClock(clockId: ClockId): Clock? = createClock(clockId)
 
-    fun getCurrentClock(): Clock {
-        val clockId = "" // TODO: Load setting
+    fun registerClockChangeListener(listener: ClockChangeListener) =
+        clockChangeListeners.add(listener)
+
+    fun unregisterClockChangeListener(listener: ClockChangeListener) =
+        clockChangeListeners.remove(listener)
+
+    fun createCurrentClock(): Clock {
+        val clockId = currentClockId
         if (!clockId.isNullOrEmpty()) {
             val clock = createClock(clockId)
             if (clock != null) {
@@ -83,12 +134,13 @@
     private fun createClock(clockId: ClockId): Clock? =
         availableClocks[clockId]?.provider?.createClock(clockId)
 
-    fun setCurrentClock(clockId: ClockId) {
-        // TODO: Write Setting
-    }
-
     private data class ClockInfo(
         val metadata: ClockMetadata,
         val provider: ClockProvider
     )
+
+    private data class ClockSetting(
+        val clockId: ClockId,
+        val _applied_timestamp: Long
+    )
 }
\ No newline at end of file