[kairos] Add logging to facilitate debugging

Flag: EXEMPT unused
Test: atest kairos-tests
Change-Id: I3858504a44fe4357c8cc7c1aa4997945eb35573e
diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt
index b688eaf..97252b4 100644
--- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt
+++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt
@@ -137,7 +137,7 @@
     override suspend fun <R> transact(block: suspend FrpTransactionScope.() -> R): R {
         val result = CompletableDeferred<R>(coroutineContext[Job])
         @Suppress("DeferredResultUnused")
-        network.transaction {
+        network.transaction("FrpNetwork.transact") {
             val buildScope =
                 BuildScopeImpl(
                     stateScope = StateScopeImpl(evalScope = this, endSignal = endSignal),
@@ -151,7 +151,7 @@
     override suspend fun activateSpec(spec: FrpSpec<*>) {
         val job =
             network
-                .transaction {
+                .transaction("FrpNetwork.activateSpec") {
                     val buildScope =
                         BuildScopeImpl(
                             stateScope = StateScopeImpl(evalScope = this, endSignal = endSignal),
@@ -166,7 +166,8 @@
     override fun <In, Out> coalescingMutableTFlow(
         coalesce: (old: Out, new: In) -> Out,
         getInitialValue: () -> Out,
-    ): CoalescingMutableTFlow<In, Out> = CoalescingMutableTFlow(coalesce, network, getInitialValue)
+    ): CoalescingMutableTFlow<In, Out> =
+        CoalescingMutableTFlow(null, coalesce, network, getInitialValue)
 
     override fun <T> mutableTFlow(): MutableTFlow<T> = MutableTFlow(network)
 
diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt
index c773d9c..a175e2e 100644
--- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt
+++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt
@@ -467,12 +467,12 @@
 @ExperimentalFrpApi
 class CoalescingMutableTFlow<In, Out>
 internal constructor(
+    internal val name: String?,
     internal val coalesce: (old: Out, new: In) -> Out,
     internal val network: Network,
     private val getInitialValue: () -> Out,
     internal val impl: InputNode<Out> = InputNode(),
 ) : TFlow<Out>() {
-    internal val name: String? = null
     internal val storage = AtomicReference(false to getInitialValue())
 
     override fun toString(): String = "${this::class.simpleName}@$hashString"
@@ -490,7 +490,7 @@
         val (scheduled, _) = storage.getAndUpdate { (_, old) -> true to coalesce(old, value) }
         if (!scheduled) {
             @Suppress("DeferredResultUnused")
-            network.transaction {
+            network.transaction("CoalescingMutableTFlow${name?.let { "($name)" }.orEmpty()}.emit") {
                 impl.visit(this, storage.getAndSet(false to getInitialValue()).second)
             }
         }
@@ -524,7 +524,9 @@
             val newEmit =
                 async(start = CoroutineStart.LAZY) {
                     jobOrNull?.join()
-                    network.transaction { impl.visit(this, value) }.await()
+                    network
+                        .transaction("MutableTFlow($name).emit") { impl.visit(this, value) }
+                        .await()
                 }
             jobOrNull = storage.getAndSet(newEmit)
             newEmit.await()
diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt
index 982d6c3..34bd509 100644
--- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt
+++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt
@@ -457,6 +457,7 @@
 
     private val input: CoalescingMutableTFlow<Deferred<T>, Deferred<T>?> =
         CoalescingMutableTFlow(
+            name = null,
             coalesce = { _, new -> new },
             network = network,
             getInitialValue = { null },
@@ -474,7 +475,7 @@
                 .cached()
         state = TStateSource(name, operatorName, initialValue, calm)
         @Suppress("DeferredResultUnused")
-        network.transaction {
+        network.transaction("MutableTState.init") {
             calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let {
                 (connection, needsEval) ->
                 state.upstreamConnection = connection
diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt
index 86f35f7..7e63849 100644
--- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt
+++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt
@@ -85,7 +85,7 @@
         builder: suspend S.() -> Unit,
     ): TFlow<A> {
         var job: Job? = null
-        val stopEmitter = newStopEmitter()
+        val stopEmitter = newStopEmitter("buildTFlow")
         // Create a child scope that will be kept alive beyond the end of this transaction.
         val childScope = coroutineScope.childScope()
         lateinit var emitter: Pair<T, S>
@@ -131,7 +131,8 @@
     ): TFlow<Out> =
         buildTFlow(
             constructFlow = { inputNode ->
-                val flow = CoalescingMutableTFlow(coalesce, network, getInitialValue, inputNode)
+                val flow =
+                    CoalescingMutableTFlow(null, coalesce, network, getInitialValue, inputNode)
                 flow to
                     object : FrpCoalescingProducerScope<In> {
                         override fun emit(value: In) {
@@ -165,7 +166,9 @@
             subRef.getAndSet(None)?.let { output ->
                 if (output is Just) {
                     @Suppress("DeferredResultUnused")
-                    network.transaction { scheduleDeactivation(output.value) }
+                    network.transaction("observeEffect cancelled") {
+                        scheduleDeactivation(output.value)
+                    }
                 }
             }
         }
@@ -266,8 +269,9 @@
         return changes to FrpDeferredValue(initOut)
     }
 
-    private fun newStopEmitter(): CoalescingMutableTFlow<Unit, Unit> =
+    private fun newStopEmitter(name: String): CoalescingMutableTFlow<Unit, Unit> =
         CoalescingMutableTFlow(
+            name = name,
             coalesce = { _, _: Unit -> },
             network = network,
             getInitialValue = {},
@@ -293,7 +297,7 @@
     }
 
     private fun mutableChildBuildScope(): BuildScopeImpl {
-        val stopEmitter = newStopEmitter()
+        val stopEmitter = newStopEmitter("mutableChildBuildScope")
         val childScope = coroutineScope.childScope()
         childScope.coroutineContext.job.invokeOnCompletion { stopEmitter.emit(Unit) }
         // Ensure that once this transaction is done, the new child scope enters the completing
diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt
index f466113..599b186 100644
--- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt
+++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt
@@ -118,12 +118,12 @@
     }
 
     /** Evaluates [block] inside of a new transaction when the network is ready. */
-    fun <R> transaction(block: suspend EvalScope.() -> R): Deferred<R> =
+    fun <R> transaction(reason: String, block: suspend EvalScope.() -> R): Deferred<R> =
         CompletableDeferred<R>(parent = coroutineScope.coroutineContext.job).also { onResult ->
             val job =
                 coroutineScope.launch {
                     inputScheduleChan.send(
-                        ScheduledAction(onStartTransaction = block, onResult = onResult)
+                        ScheduledAction(reason, onStartTransaction = block, onResult = onResult)
                     )
                 }
             onResult.invokeOnCompletion { job.cancel() }
@@ -222,6 +222,7 @@
 }
 
 internal class ScheduledAction<T>(
+    val reason: String,
     private val onResult: CompletableDeferred<T>? = null,
     private val onStartTransaction: suspend EvalScope.() -> T,
 ) {