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

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

Merge changes from topic "278068252" into udc-dev

* changes:
  Add an AutoAddRepository
  Add auto add flag
parents a55fac12 d8af4ab7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -277,6 +277,10 @@ object Flags {
    @JvmField
    val QS_PIPELINE_NEW_HOST = unreleasedFlag(504, "qs_pipeline_new_host", teamfood = false)

    // TODO(b/278068252): Tracking Bug
    @JvmField
    val QS_PIPELINE_AUTO_ADD = unreleasedFlag(505, "qs_pipeline_auto_add", teamfood = false)

    // TODO(b/254512383): Tracking Bug
    @JvmField
    val FULL_SCREEN_USER_SWITCHER =
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.pipeline.dagger

import com.android.systemui.qs.pipeline.data.repository.AutoAddRepository
import com.android.systemui.qs.pipeline.data.repository.AutoAddSettingRepository
import dagger.Binds
import dagger.Module

@Module
abstract class QSAutoAddModule {

    @Binds abstract fun bindAutoAddRepository(impl: AutoAddSettingRepository): AutoAddRepository
}
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap

@Module
@Module(includes = [QSAutoAddModule::class])
abstract class QSPipelineModule {

    /** Implementation for [TileSpecRepository] */
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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 com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
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

/** 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>>

    /** Mark a tile as having been auto-added */
    suspend fun markTileAdded(userId: Int, spec: TileSpec)

    /**
     * Unmark a tile as having been auto-added. This is used for tiles that can be auto-added
     * multiple times.
     */
    suspend fun unmarkTileAdded(userId: Int, spec: TileSpec)
}

/**
 * Implementation that tracks the auto-added tiles stored in [Settings.Secure.QS_AUTO_ADDED_TILES].
 */
@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)
                        }
                    }

                secureSettings.registerContentObserverForUser(SETTING, observer, userId)

                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()
            }
            .flowOn(bgDispatcher)
    }

    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)
        }
    }

    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()
        }
    }

    companion object {
        private const val SETTING = Settings.Secure.QS_AUTO_ADDED_TILES
        private const val DELIMITER = ","
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

package com.android.systemui.qs.pipeline.prototyping

import android.util.Log
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.pipeline.data.repository.AutoAddRepository
import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.statusbar.commandline.Command
@@ -46,6 +48,7 @@ class PrototypeCoreStartable
@Inject
constructor(
    private val tileSpecRepository: TileSpecRepository,
    private val autoAddRepository: AutoAddRepository,
    private val userRepository: UserRepository,
    private val featureFlags: FeatureFlags,
    @Application private val scope: CoroutineScope,
@@ -60,6 +63,13 @@ constructor(
                    .flatMapLatest { user -> tileSpecRepository.tilesSpecs(user.id) }
                    .collect {}
            }
            if (featureFlags.isEnabled(Flags.QS_PIPELINE_AUTO_ADD)) {
                scope.launch {
                    userRepository.selectedUserInfo
                        .flatMapLatest { user -> autoAddRepository.autoAddedTiles(user.id) }
                        .collect { tiles -> Log.d(TAG, "Auto-added tiles: $tiles") }
                }
            }
            commandRegistry.registerCommand(COMMAND, ::CommandExecutor)
        }
    }
@@ -105,5 +115,6 @@ constructor(

    companion object {
        private const val COMMAND = "qs-pipeline"
        private const val TAG = "PrototypeCoreStartable"
    }
}
Loading