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

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

Merge changes from topic "289502851" into main

* changes:
  Apply restore to repositories
  Add a QSSettingsRestoredRepository
parents 8c836c54 ee292c1e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ oneway interface IStatusBar

    void addQsTile(in ComponentName tile);
    void remQsTile(in ComponentName tile);
    void setQsTiles(in String[] tiles);
    void clickQsTile(in ComponentName tile);
    void handleSystemKey(in KeyEvent key);

+21 −0
Original line number Diff line number Diff line
@@ -20,8 +20,12 @@ import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.qs.pipeline.data.repository.DefaultTilesQSHostRepository
import com.android.systemui.qs.pipeline.data.repository.DefaultTilesRepository
import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepository
import com.android.systemui.qs.pipeline.data.repository.InstalledTilesComponentRepositoryImpl
import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredBroadcastRepository
import com.android.systemui.qs.pipeline.data.repository.QSSettingsRestoredRepository
import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
import com.android.systemui.qs.pipeline.data.repository.TileSpecSettingsRepository
import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
@@ -41,6 +45,11 @@ abstract class QSPipelineModule {
    @Binds
    abstract fun provideTileSpecRepository(impl: TileSpecSettingsRepository): TileSpecRepository

    @Binds
    abstract fun provideDefaultTilesRepository(
        impl: DefaultTilesQSHostRepository
    ): DefaultTilesRepository

    @Binds
    abstract fun bindCurrentTilesInteractor(
        impl: CurrentTilesInteractorImpl
@@ -56,6 +65,11 @@ abstract class QSPipelineModule {
    @ClassKey(QSPipelineCoreStartable::class)
    abstract fun provideCoreStartable(startable: QSPipelineCoreStartable): CoreStartable

    @Binds
    abstract fun provideQSSettingsRestoredRepository(
        impl: QSSettingsRestoredBroadcastRepository
    ): QSSettingsRestoredRepository

    companion object {
        /**
         * Provides a logging buffer for all logs related to the new Quick Settings pipeline to log
@@ -67,5 +81,12 @@ abstract class QSPipelineModule {
        fun provideQSTileListLogBuffer(factory: LogBufferFactory): LogBuffer {
            return factory.create(QSPipelineLogger.TILE_LIST_TAG, maxSize = 700, systrace = false)
        }

        @Provides
        @SysUISingleton
        @QSRestoreLog
        fun providesQSRestoreLogBuffer(factory: LogBufferFactory): LogBuffer {
            return factory.create(QSPipelineLogger.RESTORE_TAG, maxSize = 50, systrace = false)
        }
    }
}
+6 −0
Original line number Diff line number Diff line
package com.android.systemui.qs.pipeline.dagger

import javax.inject.Qualifier

/** A [LogBuffer] for the QS pipeline to track restore of associated settings. */
@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class QSRestoreLog
+10 −0
Original line number Diff line number Diff line
package com.android.systemui.qs.pipeline.data.model

import com.android.systemui.qs.pipeline.shared.TileSpec

/** Data restored from Quick Settings as part of Backup & Restore. */
data class RestoreData(
    val restoredTiles: List<TileSpec>,
    val restoredAutoAddedTiles: Set<TileSpec>,
    val userId: Int,
)
+22 −81
Original line number Diff line number Diff line
@@ -16,28 +16,19 @@

package com.android.systemui.qs.pipeline.data.repository

import android.database.ContentObserver
import android.provider.Settings
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import android.util.SparseArray
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.qs.pipeline.data.model.RestoreData
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlinx.coroutines.flow.StateFlow

/** Repository to track what QS tiles have been auto-added */
interface AutoAddRepository {

    /** Flow of tiles that have been auto-added */
    fun autoAddedTiles(userId: Int): Flow<Set<TileSpec>>
    suspend fun autoAddedTiles(userId: Int): Flow<Set<TileSpec>>

    /** Mark a tile as having been auto-added */
    suspend fun markTileAdded(userId: Int, spec: TileSpec)
@@ -47,89 +38,39 @@ interface AutoAddRepository {
     * multiple times.
     */
    suspend fun unmarkTileAdded(userId: Int, spec: TileSpec)

    suspend fun reconcileRestore(restoreData: RestoreData)
}

/**
 * Implementation that tracks the auto-added tiles stored in [Settings.Secure.QS_AUTO_ADDED_TILES].
 * Implementation of [AutoAddRepository] that delegates to an instance of [UserAutoAddRepository]
 * for each user.
 */
@SysUISingleton
class AutoAddSettingRepository
@Inject
constructor(
    private val secureSettings: SecureSettings,
    @Background private val bgDispatcher: CoroutineDispatcher,
) : AutoAddRepository {
    override fun autoAddedTiles(userId: Int): Flow<Set<TileSpec>> {
        return conflatedCallbackFlow {
                val observer =
                    object : ContentObserver(null) {
                        override fun onChange(selfChange: Boolean) {
                            trySend(Unit)
                        }
                    }
constructor(private val userAutoAddRepositoryFactory: UserAutoAddRepository.Factory) :
    AutoAddRepository {

                secureSettings.registerContentObserverForUser(SETTING, observer, userId)
    private val userAutoAddRepositories = SparseArray<UserAutoAddRepository>()

                awaitClose { secureSettings.unregisterContentObserver(observer) }
            }
            .onStart { emit(Unit) }
            .map { secureSettings.getStringForUser(SETTING, userId) ?: "" }
            .distinctUntilChanged()
            .map {
                it.split(DELIMITER).map(TileSpec::create).filter { it !is TileSpec.Invalid }.toSet()
    override suspend fun autoAddedTiles(userId: Int): Flow<Set<TileSpec>> {
        if (userId !in userAutoAddRepositories) {
            val repository = userAutoAddRepositoryFactory.create(userId)
            userAutoAddRepositories.put(userId, repository)
        }
            .flowOn(bgDispatcher)
        return userAutoAddRepositories.get(userId).autoAdded()
    }

    override suspend fun markTileAdded(userId: Int, spec: TileSpec) {
        if (spec is TileSpec.Invalid) {
            return
        }
        val added = load(userId).toMutableSet()
        if (added.add(spec)) {
            store(userId, added)
        }
        userAutoAddRepositories.get(userId)?.markTileAdded(spec)
    }

    override suspend fun unmarkTileAdded(userId: Int, spec: TileSpec) {
        if (spec is TileSpec.Invalid) {
            return
        }
        val added = load(userId).toMutableSet()
        if (added.remove(spec)) {
            store(userId, added)
        }
    }

    private suspend fun store(userId: Int, tiles: Set<TileSpec>) {
        val toStore =
            tiles
                .filter { it !is TileSpec.Invalid }
                .joinToString(DELIMITER, transform = TileSpec::spec)
        withContext(bgDispatcher) {
            secureSettings.putStringForUser(
                SETTING,
                toStore,
                null,
                false,
                userId,
                true,
            )
        }
    }

    private suspend fun load(userId: Int): Set<TileSpec> {
        return withContext(bgDispatcher) {
            (secureSettings.getStringForUser(SETTING, userId) ?: "")
                .split(",")
                .map(TileSpec::create)
                .filter { it !is TileSpec.Invalid }
                .toSet()
        }
        userAutoAddRepositories.get(userId)?.unmarkTileAdded(spec)
    }

    companion object {
        private const val SETTING = Settings.Secure.QS_AUTO_ADDED_TILES
        private const val DELIMITER = ","
    override suspend fun reconcileRestore(restoreData: RestoreData) {
        userAutoAddRepositories.get(restoreData.userId)?.reconcileRestore(restoreData)
    }
}
Loading