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

Commit 61c86567 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Tile perf: offload tile viewmodel and data to bg" into main

parents 372fece2 55e5468a
Loading
Loading
Loading
Loading
+20 −25
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles.base.viewmodel

import android.os.UserHandle
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.Dumpable
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics
@@ -58,11 +59,8 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext

/**
 * Provides a hassle-free way to implement new tiles according to current System UI architecture
@@ -90,36 +88,35 @@ class QSTileViewModelImpl<DATA_TYPE>(

    private val users: MutableStateFlow<UserHandle> =
        MutableStateFlow(userRepository.getSelectedUserInfo().userHandle)

    private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow()

    private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow()
    private val spec
        get() = config.tileSpec

    private val tileData: SharedFlow<DATA_TYPE> = createTileDataFlow()
    private val tileData: SharedFlow<DATA_TYPE?> = createTileDataFlow()

    override val state: StateFlow<QSTileState?> =
        tileData
            .map { data ->
                withContext(uiBackgroundDispatcher) { mapper().map(config, data) }
                    .also { state -> qsTileLogger.logStateUpdate(spec, state, data) }
                data?.let {
                    mapper().map(config, it).also { state ->
                        qsTileLogger.logStateUpdate(spec, state, it)
                    }
            .stateIn(
                tileScope,
                SharingStarted.WhileSubscribed(),
                null,
            )
                }
            }
            .flowOn(uiBackgroundDispatcher)
            .stateIn(tileScope, SharingStarted.WhileSubscribed(), null)

    override val isAvailable: StateFlow<Boolean> =
        users
            .flatMapLatest { tileDataInteractor().availability(it) }
            .flowOn(backgroundDispatcher)
            .stateIn(
                tileScope,
                SharingStarted.WhileSubscribed(),
                true,
            )
            .stateIn(tileScope, SharingStarted.WhileSubscribed(), true)

    override fun forceUpdate() {
        tileScope.launch { forceUpdates.emit(Unit) }
        tileScope.launch(context = backgroundDispatcher) { forceUpdates.emit(Unit) }
    }

    override fun onUserChanged(user: UserHandle) {
@@ -131,9 +128,9 @@ class QSTileViewModelImpl<DATA_TYPE>(
            userAction,
            spec,
            tileData.replayCache.isNotEmpty(),
            state.replayCache.isNotEmpty()
            state.replayCache.isNotEmpty(),
        )
        tileScope.launch { userInputs.emit(userAction) }
        tileScope.launch(context = backgroundDispatcher) { userInputs.emit(userAction) }
    }

    override fun destroy() {
@@ -147,7 +144,7 @@ class QSTileViewModelImpl<DATA_TYPE>(
            println(state.replayCache.lastOrNull().toString())
        }

    private fun createTileDataFlow(): SharedFlow<DATA_TYPE> =
    private fun createTileDataFlow(): SharedFlow<DATA_TYPE?> =
        users
            .transformLatest { user ->
                coroutineScope {
@@ -159,6 +156,7 @@ class QSTileViewModelImpl<DATA_TYPE>(
                                    .onEach { qsTileLogger.logForceUpdate(spec) },
                            )
                            .onStart { qsTileLogger.logInitialRequest(spec) }
                            .flowOn(backgroundDispatcher)
                            .stateIn(this, SharingStarted.Eagerly, DataUpdateTrigger.InitialRequest)
                    tileDataInteractor()
                        .tileData(user, updateTriggers)
@@ -171,11 +169,8 @@ class QSTileViewModelImpl<DATA_TYPE>(
                }
            }
            .distinctUntilChanged()
            .shareIn(
                tileScope,
                SharingStarted.WhileSubscribed(),
                replay = 1, // we only care about the most recent value
            )
            .flowOn(backgroundDispatcher)
            .stateIn(tileScope, SharingStarted.WhileSubscribed(), null)

    /**
     * Creates a user input flow which: