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

Commit ccfadcfd authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Do not remove work tile from inside the tile." into main

parents aec03f18 c018d4b3
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -675,6 +675,24 @@ class CurrentTilesInteractorImplTest : SysuiTestCase() {
            assertThat(tiles!!.size).isEqualTo(3)
        }

    @Test
    fun changeInPackagesTiles_doesntTriggerUserChange_logged() =
        testScope.runTest(USER_INFO_0) {
            val specs =
                listOf(
                    TileSpec.create("a"),
                )
            tileSpecRepository.setTiles(USER_INFO_0.id, specs)
            runCurrent()
            // Settled on the same list of tiles.
            assertThat(underTest.currentTilesSpecs).isEqualTo(specs)

            installedTilesPackageRepository.setInstalledPackagesForUser(USER_INFO_0.id, emptySet())
            runCurrent()

            verify(logger, never()).logTileUserChanged(TileSpec.create("a"), 0)
        }

    private fun QSTile.State.fillIn(state: Int, label: CharSequence, secondaryLabel: CharSequence) {
        this.state = state
        this.label = label
+100 −104
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ import com.android.systemui.qs.toProto
import com.android.systemui.retail.data.repository.RetailModeRepository
import com.android.systemui.settings.UserTracker
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.pairwiseBy
import dagger.Lazy
import java.io.PrintWriter
import javax.inject.Inject
@@ -63,7 +63,6 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

@@ -169,16 +168,18 @@ constructor(
    private val userAndTiles =
        currentUser
            .flatMapLatest { userId ->
                tileSpecRepository.tilesSpecs(userId).map { UserAndTiles(userId, it) }
                val currentTiles = tileSpecRepository.tilesSpecs(userId)
                val installedComponents =
                    installedTilesComponentRepository.getInstalledTilesComponents(userId)
                currentTiles.combine(installedComponents) { tiles, components ->
                    UserTilesAndComponents(userId, tiles, components)
                }
            }
            .distinctUntilChanged()
            .pairwise(UserAndTiles(-1, emptyList()))
            .flowOn(backgroundDispatcher)

    private val installedPackagesWithTiles =
        currentUser.flatMapLatest {
            installedTilesComponentRepository.getInstalledTilesComponents(it)
            .pairwiseBy(UserTilesAndComponents(-1, emptyList(), emptySet())) { prev, new ->
                DataWithUserChange(data = new, userChange = prev.userId != new.userId)
            }
            .flowOn(backgroundDispatcher)

    private val minTiles: Int
        get() =
@@ -194,7 +195,6 @@ constructor(
        }
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    private fun startTileCollection() {
        scope.launch {
            launch {
@@ -205,25 +205,15 @@ constructor(
            }

            launch(backgroundDispatcher) {
                userAndTiles
                    .combine(installedPackagesWithTiles) { usersAndTiles, packages ->
                        Data(
                            usersAndTiles.previousValue,
                            usersAndTiles.newValue,
                            packages,
                        )
                    }
                    .collectLatest {
                        val newTileList = it.newData.tiles
                        val userChanged = it.oldData.userId != it.newData.userId
                        val newUser = it.newData.userId
                userAndTiles.collectLatest {
                    val newUser = it.userId
                    val newTileList = it.tiles
                    val components = it.installedComponents
                    val userChanged = it.userChange

                    // Destroy all tiles that are not in the new set
                    specsToTiles
                            .filter {
                                it.key !in newTileList && it.value is TileOrNotInstalled.Tile
                            }
                        .filter { it.key !in newTileList && it.value is TileOrNotInstalled.Tile }
                        .forEach { entry ->
                            logger.logTileDestroyed(
                                entry.key,
@@ -256,8 +246,7 @@ constructor(
                                            specsToTiles.getValue(tileSpec),
                                            userChanged,
                                            newUser
                                            )
                                                ?: createTile(tileSpec)
                                        ) ?: createTile(tileSpec)
                                    } else {
                                        createTile(tileSpec)
                                    }
@@ -274,9 +263,7 @@ constructor(
                    val newResolvedTiles =
                        newTileMap
                            .filter { it.value is TileOrNotInstalled.Tile }
                                .map {
                                    TileModel(it.key, (it.value as TileOrNotInstalled.Tile).tile)
                                }
                            .map { TileModel(it.key, (it.value as TileOrNotInstalled.Tile).tile) }

                    _currentSpecsAndTiles.value = newResolvedTiles
                    logger.logTilesNotInstalled(
@@ -362,8 +349,7 @@ constructor(
                    newQSTileFactory.get().createTile(spec.spec)
                } else {
                    null
                }
                    ?: tileFactory.createTile(spec.spec)
                } ?: tileFactory.createTile(spec.spec)
            }
        if (tile == null) {
            logger.logTileNotFoundInFactory(spec)
@@ -436,15 +422,25 @@ constructor(

        @JvmInline value class Tile(val tile: QSTile) : TileOrNotInstalled
    }
}

    private data class UserAndTiles(
private data class UserTilesAndComponents(
    val userId: Int,
    val tiles: List<TileSpec>,
    val installedComponents: Set<ComponentName>
)

    private data class Data(
        val oldData: UserAndTiles,
        val newData: UserAndTiles,
private data class DataWithUserChange(
    val userId: Int,
    val tiles: List<TileSpec>,
    val installedComponents: Set<ComponentName>,
    val userChange: Boolean,
)

private fun DataWithUserChange(data: UserTilesAndComponents, userChange: Boolean) =
    DataWithUserChange(
        data.userId,
        data.tiles,
        data.installedComponents,
        userChange,
    )
}
+2 −1
Original line number Diff line number Diff line
@@ -106,7 +106,8 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements
    @Override
    @MainThread
    public void onManagedProfileRemoved() {
        mHost.removeTile(getTileSpec());
        // No OP as this may race with the user change in CurrentTilesInteractor.
        // If the tile needs to be removed, AutoAdd (or AutoTileManager) will take care of that.
    }

    @Override
+6 −1
Original line number Diff line number Diff line
@@ -22,12 +22,15 @@ import androidx.annotation.StringRes
import com.android.internal.logging.InstanceId
import com.android.systemui.qs.pipeline.shared.TileSpec

data class QSTileConfig(
data class QSTileConfig
@JvmOverloads
constructor(
    val tileSpec: TileSpec,
    val uiConfig: QSTileUIConfig,
    val instanceId: InstanceId,
    val metricsSpec: String = tileSpec.spec,
    val policy: QSTilePolicy = QSTilePolicy.NoRestrictions,
    val autoRemoveOnUnavailable: Boolean = true,
)

/**
@@ -38,6 +41,7 @@ sealed interface QSTileUIConfig {

    val iconRes: Int
        @DrawableRes get

    val labelRes: Int
        @StringRes get

@@ -48,6 +52,7 @@ sealed interface QSTileUIConfig {
    data object Empty : QSTileUIConfig {
        override val iconRes: Int
            get() = Resources.ID_NULL

        override val labelRes: Int
            get() = Resources.ID_NULL
    }
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ constructor(
            applicationScope.launch {
                launch {
                    qsTileViewModel.isAvailable.collectIndexed { index, isAvailable ->
                        if (!isAvailable) {
                        if (!isAvailable && qsTileViewModel.config.autoRemoveOnUnavailable) {
                            qsHost.removeTile(tileSpec)
                        }
                        // qsTileViewModel.isAvailable flow often starts with isAvailable == true.
Loading