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

Commit c018d4b3 authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Do not remove work tile from inside the tile.

AutoAddable will take care of removing it for the correct user, as it
gets its user from CurrentTilesInteractor.

Also, fix user switch in CurrentTilesInteractor. It was triggering more
often than it should.

Test: manual
Fixes: 352008994
Flag: EXEMPT bugfix
Change-Id: If1b66e06649566335ee904e3d40f11cc3c921064
parent 8a225631
Loading
Loading
Loading
Loading
+18 −0
Original line number Original line Diff line number Diff line
@@ -675,6 +675,24 @@ class CurrentTilesInteractorImplTest : SysuiTestCase() {
            assertThat(tiles!!.size).isEqualTo(3)
            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) {
    private fun QSTile.State.fillIn(state: Int, label: CharSequence, secondaryLabel: CharSequence) {
        this.state = state
        this.state = state
        this.label = label
        this.label = label
+100 −104
Original line number Original line 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.retail.data.repository.RetailModeRepository
import com.android.systemui.settings.UserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.user.data.repository.UserRepository
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 dagger.Lazy
import java.io.PrintWriter
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Inject
@@ -63,7 +63,6 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withContext


@@ -169,16 +168,18 @@ constructor(
    private val userAndTiles =
    private val userAndTiles =
        currentUser
        currentUser
            .flatMapLatest { userId ->
            .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()
            .distinctUntilChanged()
            .pairwise(UserAndTiles(-1, emptyList()))
            .pairwiseBy(UserTilesAndComponents(-1, emptyList(), emptySet())) { prev, new ->
            .flowOn(backgroundDispatcher)
                DataWithUserChange(data = new, userChange = prev.userId != new.userId)

    private val installedPackagesWithTiles =
        currentUser.flatMapLatest {
            installedTilesComponentRepository.getInstalledTilesComponents(it)
            }
            }
            .flowOn(backgroundDispatcher)


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


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


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


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


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


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


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


    private data class Data(
private data class DataWithUserChange(
        val oldData: UserAndTiles,
    val userId: Int,
        val newData: UserAndTiles,
    val tiles: List<TileSpec>,
    val installedComponents: Set<ComponentName>,
    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 Original line Diff line number Diff line
@@ -106,7 +106,8 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements
    @Override
    @Override
    @MainThread
    @MainThread
    public void onManagedProfileRemoved() {
    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
    @Override
+6 −1
Original line number Original line Diff line number Diff line
@@ -22,12 +22,15 @@ import androidx.annotation.StringRes
import com.android.internal.logging.InstanceId
import com.android.internal.logging.InstanceId
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.pipeline.shared.TileSpec


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


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


    val iconRes: Int
    val iconRes: Int
        @DrawableRes get
        @DrawableRes get

    val labelRes: Int
    val labelRes: Int
        @StringRes get
        @StringRes get


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

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