Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 576b95bf authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Prevent initial empty state to be propagated in DisplayRepository

Depending on timings, it was possible for the `scan` to propagate the initial state first before calculating the next state based on available display ids.
In this cl the initial state is filtered out, and a log.wtf is added in the case enabledDisplays is empty (which should never happen)

Bug: 361989878
Test: DisplayRepositoryTest#displayFlow_onlyDefaultDisplayAvailable_neverEmitsEmptySet
Flag: NONE small bugfix
Change-Id: I7b7ee6883ca5b5fd95304a0a5f1168d8b5ce2e4e
parent c30ba623
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.shareIn
@@ -184,6 +185,9 @@ constructor(
        if (Flags.enableEfficientDisplayRepository()) {
            enabledDisplayIds
                .mapElementsLazily { displayId -> getDisplay(displayId) }
                .onEach {
                    if (it.isEmpty()) Log.wtf(TAG, "No enabled displays. This should never happen.")
                }
                .flowOn(backgroundCoroutineDispatcher)
                .debugLog("enabledDisplays")
                .stateIn(
@@ -194,7 +198,8 @@ constructor(
                    // performance concerns.
                    // Ultimately, this is a trade-off between a one-time UI thread binder call and
                    // the constant overhead of sharedFlows.
                    initialValue = getDisplays())
                    initialValue = getDisplays()
                )
        } else {
            oldEnabledDisplays
        }
@@ -380,9 +385,8 @@ constructor(
            val resultSet: Set<V>
        )

        val initialState = State(emptySet<T>(), emptyMap(), emptySet<V>())

        return this.scan(initialState) { state, currentSet ->
        val emptyInitialState = State(emptySet<T>(), emptyMap(), emptySet<V>())
        return this.scan(emptyInitialState) { state, currentSet ->
                if (currentSet == state.previousSet) {
                    state
                } else {
@@ -397,6 +401,7 @@ constructor(
                    State(currentSet, newMap, resultSet)
                }
            }
            .filter { it != emptyInitialState }
            .map { it.resultSet }
    }

+10 −0
Original line number Diff line number Diff line
@@ -467,6 +467,16 @@ class DisplayRepositoryTest : SysuiTestCase() {
            assertThat(values.toIdSets()).containsExactly(setOf(0, 1, 2))
        }

    @Test
    fun displayFlow_onlyDefaultDisplayAvailable_neverEmitsEmptySet() =
        testScope.runTest {
            setDisplays(0)

            val values: List<Set<Display>> by collectValues(displayRepository.displays)

            assertThat(values.toIdSets()).containsExactly(setOf(0))
        }

    private fun Iterable<Display>.ids(): List<Int> = map { it.displayId }

    private fun Iterable<Set<Display>>.toIdSets(): List<Set<Int>> = map { it.ids().toSet() }