Loading packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/State.kt +4 −11 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.kairos import com.android.systemui.kairos.internal.CompletableLazy import com.android.systemui.kairos.internal.EventsImpl import com.android.systemui.kairos.internal.Init import com.android.systemui.kairos.internal.InitScope import com.android.systemui.kairos.internal.Network Loading @@ -28,7 +27,7 @@ import com.android.systemui.kairos.internal.StateSource import com.android.systemui.kairos.internal.activated import com.android.systemui.kairos.internal.constInit import com.android.systemui.kairos.internal.constState import com.android.systemui.kairos.internal.filterImpl import com.android.systemui.kairos.internal.distinctChanges import com.android.systemui.kairos.internal.flatMapStateImpl import com.android.systemui.kairos.internal.init import com.android.systemui.kairos.internal.mapImpl Loading Loading @@ -247,21 +246,15 @@ internal constructor( internal val state = run { val changes = input.impl val state: StateSource<T> = StateSource(initialValue, nameData) val mapImpl = mapImpl(upstream = { changes.activated() }, nameData + "forceValue") { it, _ -> it!!.value } val calm: EventsImpl<T> = filterImpl(nameData + "calm", { mapImpl }) { new -> new != state.getCurrentWithEpoch(evalScope = this).first } val forced = mapImpl({ changes.activated() }, nameData + "forced") { it, _ -> it!!.value } val calm = distinctChanges({ forced }, nameData + "calm", state) @Suppress("DeferredResultUnused") network.transaction("MutableState.init") { calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let { (connection, needsEval) -> state.upstreamConnection = connection if (needsEval) { schedule(state) state.schedule(0, this) } } } Loading packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/StateScope.kt +8 −7 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import com.android.systemui.kairos.util.NameTag import com.android.systemui.kairos.util.WithPrev import com.android.systemui.kairos.util.map import com.android.systemui.kairos.util.mapMaybeValues import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.nameTag import com.android.systemui.kairos.util.plus import com.android.systemui.kairos.util.toNameData Loading Loading @@ -1256,7 +1257,7 @@ internal fun <A, B> StateScope.applyLatestStateful( init: Stateful<A>, ): Pair<Events<B>, DeferredValue<A>> { val singletonMap = events.mapCheap(nameData + "singletonMap") { spec -> mapOf(Unit to Maybe.present(spec)) } events.mapCheap(nameData + "singletonMap") { spec -> mapOf(Unit to maybeOf(spec)) } val (events, result) = applyLatestStatefulForKey(nameData, singletonMap, init = mapOf(Unit to init), numKeys = 1) val outEvents: Events<B> = Loading Loading @@ -1403,7 +1404,7 @@ internal fun <A> StateScope.childStateScope( ): DeferredValue<A> { val turnOff = nextOnly(nameData + "onlyOne", stop).mapCheap(nameData + "turnOff") { mapOf(Unit to Maybe.absent<Stateful<A>>()) mapOf(Unit to maybeOf<Stateful<A>>()) } val (_, init: DeferredValue<Map<Unit, A>>) = applyLatestStatefulForKey(nameData, turnOff, init = mapOf(Unit to stateful), numKeys = 1) Loading Loading @@ -1464,8 +1465,8 @@ internal fun <A> StateScope.pairwise( nameData: NameData, events: Events<A>, ): Events<WithPrev<A, A>> { val mapPresent = events.mapCheap(nameData + "mapPresent") { Maybe.present(it) } val pairwise = pairwise(nameData, mapPresent, Maybe.absent) val mapPresent = events.mapCheap(nameData + "mapPresent") { maybeOf(it) } val pairwise = pairwise(nameData, mapPresent, maybeOf()) return pairwise.mapMaybe(nameData + "zipMaybe") { (prev, next) -> prev.zipWith(next, ::WithPrev) } Loading Loading @@ -1518,8 +1519,8 @@ internal fun <A, B, C> StateScope.sample( val state = holdState( nameData + "otherStore", other.mapCheap(nameData + "mapOtherPresent") { Maybe.present(it) }, Maybe.absent, other.mapCheap(nameData + "mapOtherPresent") { maybeOf(it) }, maybeOf(), ) return events .map(nameData) { a -> state.sample().map { transform(a, it) } } Loading Loading @@ -1639,7 +1640,7 @@ internal fun <K, V> StateScope.filterIncrementally( ): Incremental<K, V> = mapIncrementalState(nameData, incremental) { entry -> transform(entry).map(nameData + { "filter[key=${entry.key}]" }) { if (it) Maybe.present(entry.value) else Maybe.absent if (it) maybeOf(entry.value) else maybeOf() } } Loading packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TransactionScope.kt +4 −4 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.systemui.kairos import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.These import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.nameTag import com.android.systemui.kairos.util.plus import com.android.systemui.kairos.util.toNameData Loading Loading @@ -166,10 +166,10 @@ internal fun <A, B, C> Events<A>.samplePromptly( .mapMaybe(nameData) { these -> when (these) { // both present, transform the upstream value and the new value is These.Both -> Maybe.present(transform(these.first.first, these.second)) is These.Both -> maybeOf(transform(these.first.first, these.second)) // no upstream present, so don't perform the sample is These.Second -> Maybe.absent() is These.Second -> maybeOf() // just the upstream, so transform the upstream and the old value is These.First -> Maybe.present(transform(these.value.first, these.value.second)) is These.First -> maybeOf(transform(these.value.first, these.value.second)) } } packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt +26 −20 Original line number Diff line number Diff line Loading @@ -47,7 +47,6 @@ import com.android.systemui.kairos.util.Maybe.Absent import com.android.systemui.kairos.util.Maybe.Present import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.NameTag import com.android.systemui.kairos.util.appendNames import com.android.systemui.kairos.util.forceInit import com.android.systemui.kairos.util.map import com.android.systemui.kairos.util.mapName Loading Loading @@ -192,28 +191,36 @@ internal class BuildScopeImpl( name: NameTag?, ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> { val nameData = name.toNameData("Events.applyLatestSpecForKey") val eventsByKey: KeyedEvents<K, Maybe<BuildSpec<A>>> = groupByKey(numKeys) val eventsByKey: KeyedEvents<K, Maybe<BuildSpec<A>>> = groupByKey(nameData + "eventsByKey", numKeys) val childCoroutineScope = coroutineScope.childScope() val initOut: Lazy<Map<K, B>> = deferAsync { // swap out the CoroutineScope used for this build scope with the child scope reenterBuildScope(this@BuildScopeImpl, childCoroutineScope).run { initialSpecs.unwrapped.value.mapValues { (k, spec) -> val newEnd = eventsByKey[k] val newScope = childBuildScope(newEnd, nameData.mapName { "$it[key=$k]" }) val newEnd: Events<Maybe<BuildSpec<A>>> = eventsByKey[k] val newScope = childBuildScope( newEnd, nameData.mapName { "$it[key=$k, epoch=$epoch, init=true]" }, ) newScope.spec() } } // TODO: should this also be used for the initOut? val childScope = coroutineScope.childScope() } val changesImpl: EventsImpl<Map<K, Maybe<A>>> = mapImpl( upstream = { this@applyLatestSpecForKey.init.connect(evalScope = this) }, nameData + "changes", ) { upstreamMap, _ -> reenterBuildScope(this@BuildScopeImpl, childScope).run { reenterBuildScope(this@BuildScopeImpl, childCoroutineScope).run { upstreamMap.mapValues { (k: K, ma: Maybe<BuildSpec<A>>) -> ma.map { spec -> val newEnd = skipNext(nameData.mapName { "$it[key=$k]-newEnd" }, eventsByKey[k]) val newScope = childBuildScope(newEnd, nameData.mapName { "$it[key=$k]" }) val newName = nameData.mapName { "$it[key=$k, epoch=$epoch, init = false]" } val newEnd: Events<Maybe<BuildSpec<A>>> = skipNext(newName + "newEnd", eventsByKey[k]) val newScope = childBuildScope(newEnd, newName) newScope.spec() } } Loading Loading @@ -289,21 +296,20 @@ internal class BuildScopeImpl( name: NameTag?, block: suspend KairosCoroutineScope.() -> R, ): Deferred<R> { val asynaNameData = name.toNameData("EffectScope.async") val asyncNameData = name.toNameData("EffectScope.async") return childScope.async(context, start) newScope@{ val childEndSignal: Events<Unit> = this@BuildScopeImpl.newStopEmitter( asynaNameData.appendNames("childEndSignal") ) .apply { this@newScope.invokeOnCancel { emit(Unit) } } this@BuildScopeImpl.newStopEmitter(asyncNameData + "childEndSignal").apply { this@newScope.invokeOnCancel { emit(Unit) } } val childStateScope: StateScopeImpl = this@BuildScopeImpl.stateScope.childStateScope( childEndSignal, asynaNameData, asyncNameData, ) val localNetwork = LocalNetwork( asynaNameData, asyncNameData, network = this@BuildScopeImpl.network, scope = this@newScope, aliveLazy = childStateScope.aliveLazy, Loading packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt +2 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.systemui.kairos.internal.store.SingletonMapK import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.Maybe.Present import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.plus internal inline fun <A> filterPresentImpl( Loading @@ -47,8 +48,6 @@ internal inline fun <A> filterImpl( crossinline f: EvalScope.(A) -> Boolean, ): EventsImpl<A> { val mapped = mapImpl(getPulse, nameData + "toMaybe") { it, _ -> if (f(it)) Maybe.present(it) else Maybe.absent } mapImpl(getPulse, nameData + "toMaybe") { it, _ -> if (f(it)) maybeOf(it) else maybeOf() } return filterPresentImpl(nameData) { mapped } } Loading
packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/State.kt +4 −11 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.kairos import com.android.systemui.kairos.internal.CompletableLazy import com.android.systemui.kairos.internal.EventsImpl import com.android.systemui.kairos.internal.Init import com.android.systemui.kairos.internal.InitScope import com.android.systemui.kairos.internal.Network Loading @@ -28,7 +27,7 @@ import com.android.systemui.kairos.internal.StateSource import com.android.systemui.kairos.internal.activated import com.android.systemui.kairos.internal.constInit import com.android.systemui.kairos.internal.constState import com.android.systemui.kairos.internal.filterImpl import com.android.systemui.kairos.internal.distinctChanges import com.android.systemui.kairos.internal.flatMapStateImpl import com.android.systemui.kairos.internal.init import com.android.systemui.kairos.internal.mapImpl Loading Loading @@ -247,21 +246,15 @@ internal constructor( internal val state = run { val changes = input.impl val state: StateSource<T> = StateSource(initialValue, nameData) val mapImpl = mapImpl(upstream = { changes.activated() }, nameData + "forceValue") { it, _ -> it!!.value } val calm: EventsImpl<T> = filterImpl(nameData + "calm", { mapImpl }) { new -> new != state.getCurrentWithEpoch(evalScope = this).first } val forced = mapImpl({ changes.activated() }, nameData + "forced") { it, _ -> it!!.value } val calm = distinctChanges({ forced }, nameData + "calm", state) @Suppress("DeferredResultUnused") network.transaction("MutableState.init") { calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let { (connection, needsEval) -> state.upstreamConnection = connection if (needsEval) { schedule(state) state.schedule(0, this) } } } Loading
packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/StateScope.kt +8 −7 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import com.android.systemui.kairos.util.NameTag import com.android.systemui.kairos.util.WithPrev import com.android.systemui.kairos.util.map import com.android.systemui.kairos.util.mapMaybeValues import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.nameTag import com.android.systemui.kairos.util.plus import com.android.systemui.kairos.util.toNameData Loading Loading @@ -1256,7 +1257,7 @@ internal fun <A, B> StateScope.applyLatestStateful( init: Stateful<A>, ): Pair<Events<B>, DeferredValue<A>> { val singletonMap = events.mapCheap(nameData + "singletonMap") { spec -> mapOf(Unit to Maybe.present(spec)) } events.mapCheap(nameData + "singletonMap") { spec -> mapOf(Unit to maybeOf(spec)) } val (events, result) = applyLatestStatefulForKey(nameData, singletonMap, init = mapOf(Unit to init), numKeys = 1) val outEvents: Events<B> = Loading Loading @@ -1403,7 +1404,7 @@ internal fun <A> StateScope.childStateScope( ): DeferredValue<A> { val turnOff = nextOnly(nameData + "onlyOne", stop).mapCheap(nameData + "turnOff") { mapOf(Unit to Maybe.absent<Stateful<A>>()) mapOf(Unit to maybeOf<Stateful<A>>()) } val (_, init: DeferredValue<Map<Unit, A>>) = applyLatestStatefulForKey(nameData, turnOff, init = mapOf(Unit to stateful), numKeys = 1) Loading Loading @@ -1464,8 +1465,8 @@ internal fun <A> StateScope.pairwise( nameData: NameData, events: Events<A>, ): Events<WithPrev<A, A>> { val mapPresent = events.mapCheap(nameData + "mapPresent") { Maybe.present(it) } val pairwise = pairwise(nameData, mapPresent, Maybe.absent) val mapPresent = events.mapCheap(nameData + "mapPresent") { maybeOf(it) } val pairwise = pairwise(nameData, mapPresent, maybeOf()) return pairwise.mapMaybe(nameData + "zipMaybe") { (prev, next) -> prev.zipWith(next, ::WithPrev) } Loading Loading @@ -1518,8 +1519,8 @@ internal fun <A, B, C> StateScope.sample( val state = holdState( nameData + "otherStore", other.mapCheap(nameData + "mapOtherPresent") { Maybe.present(it) }, Maybe.absent, other.mapCheap(nameData + "mapOtherPresent") { maybeOf(it) }, maybeOf(), ) return events .map(nameData) { a -> state.sample().map { transform(a, it) } } Loading Loading @@ -1639,7 +1640,7 @@ internal fun <K, V> StateScope.filterIncrementally( ): Incremental<K, V> = mapIncrementalState(nameData, incremental) { entry -> transform(entry).map(nameData + { "filter[key=${entry.key}]" }) { if (it) Maybe.present(entry.value) else Maybe.absent if (it) maybeOf(entry.value) else maybeOf() } } Loading
packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TransactionScope.kt +4 −4 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.systemui.kairos import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.These import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.nameTag import com.android.systemui.kairos.util.plus import com.android.systemui.kairos.util.toNameData Loading Loading @@ -166,10 +166,10 @@ internal fun <A, B, C> Events<A>.samplePromptly( .mapMaybe(nameData) { these -> when (these) { // both present, transform the upstream value and the new value is These.Both -> Maybe.present(transform(these.first.first, these.second)) is These.Both -> maybeOf(transform(these.first.first, these.second)) // no upstream present, so don't perform the sample is These.Second -> Maybe.absent() is These.Second -> maybeOf() // just the upstream, so transform the upstream and the old value is These.First -> Maybe.present(transform(these.value.first, these.value.second)) is These.First -> maybeOf(transform(these.value.first, these.value.second)) } }
packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt +26 −20 Original line number Diff line number Diff line Loading @@ -47,7 +47,6 @@ import com.android.systemui.kairos.util.Maybe.Absent import com.android.systemui.kairos.util.Maybe.Present import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.NameTag import com.android.systemui.kairos.util.appendNames import com.android.systemui.kairos.util.forceInit import com.android.systemui.kairos.util.map import com.android.systemui.kairos.util.mapName Loading Loading @@ -192,28 +191,36 @@ internal class BuildScopeImpl( name: NameTag?, ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> { val nameData = name.toNameData("Events.applyLatestSpecForKey") val eventsByKey: KeyedEvents<K, Maybe<BuildSpec<A>>> = groupByKey(numKeys) val eventsByKey: KeyedEvents<K, Maybe<BuildSpec<A>>> = groupByKey(nameData + "eventsByKey", numKeys) val childCoroutineScope = coroutineScope.childScope() val initOut: Lazy<Map<K, B>> = deferAsync { // swap out the CoroutineScope used for this build scope with the child scope reenterBuildScope(this@BuildScopeImpl, childCoroutineScope).run { initialSpecs.unwrapped.value.mapValues { (k, spec) -> val newEnd = eventsByKey[k] val newScope = childBuildScope(newEnd, nameData.mapName { "$it[key=$k]" }) val newEnd: Events<Maybe<BuildSpec<A>>> = eventsByKey[k] val newScope = childBuildScope( newEnd, nameData.mapName { "$it[key=$k, epoch=$epoch, init=true]" }, ) newScope.spec() } } // TODO: should this also be used for the initOut? val childScope = coroutineScope.childScope() } val changesImpl: EventsImpl<Map<K, Maybe<A>>> = mapImpl( upstream = { this@applyLatestSpecForKey.init.connect(evalScope = this) }, nameData + "changes", ) { upstreamMap, _ -> reenterBuildScope(this@BuildScopeImpl, childScope).run { reenterBuildScope(this@BuildScopeImpl, childCoroutineScope).run { upstreamMap.mapValues { (k: K, ma: Maybe<BuildSpec<A>>) -> ma.map { spec -> val newEnd = skipNext(nameData.mapName { "$it[key=$k]-newEnd" }, eventsByKey[k]) val newScope = childBuildScope(newEnd, nameData.mapName { "$it[key=$k]" }) val newName = nameData.mapName { "$it[key=$k, epoch=$epoch, init = false]" } val newEnd: Events<Maybe<BuildSpec<A>>> = skipNext(newName + "newEnd", eventsByKey[k]) val newScope = childBuildScope(newEnd, newName) newScope.spec() } } Loading Loading @@ -289,21 +296,20 @@ internal class BuildScopeImpl( name: NameTag?, block: suspend KairosCoroutineScope.() -> R, ): Deferred<R> { val asynaNameData = name.toNameData("EffectScope.async") val asyncNameData = name.toNameData("EffectScope.async") return childScope.async(context, start) newScope@{ val childEndSignal: Events<Unit> = this@BuildScopeImpl.newStopEmitter( asynaNameData.appendNames("childEndSignal") ) .apply { this@newScope.invokeOnCancel { emit(Unit) } } this@BuildScopeImpl.newStopEmitter(asyncNameData + "childEndSignal").apply { this@newScope.invokeOnCancel { emit(Unit) } } val childStateScope: StateScopeImpl = this@BuildScopeImpl.stateScope.childStateScope( childEndSignal, asynaNameData, asyncNameData, ) val localNetwork = LocalNetwork( asynaNameData, asyncNameData, network = this@BuildScopeImpl.network, scope = this@newScope, aliveLazy = childStateScope.aliveLazy, Loading
packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt +2 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import com.android.systemui.kairos.internal.store.SingletonMapK import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.Maybe.Present import com.android.systemui.kairos.util.NameData import com.android.systemui.kairos.util.maybeOf import com.android.systemui.kairos.util.plus internal inline fun <A> filterPresentImpl( Loading @@ -47,8 +48,6 @@ internal inline fun <A> filterImpl( crossinline f: EvalScope.(A) -> Boolean, ): EventsImpl<A> { val mapped = mapImpl(getPulse, nameData + "toMaybe") { it, _ -> if (f(it)) Maybe.present(it) else Maybe.absent } mapImpl(getPulse, nameData + "toMaybe") { it, _ -> if (f(it)) maybeOf(it) else maybeOf() } return filterPresentImpl(nameData) { mapped } }