summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2025-02-06 07:47:38 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-06 07:47:38 -0800
commite80f1b9a275793715dd7279e2ab352ed56e72e94 (patch)
tree00447a339603e31870b4a1172a18732e8108bb88
parent644ed4e9944e6be5685d7750552e5b78a566b10b (diff)
parentb02dd916fc279fbf7a41100c87e334abb94bf30d (diff)
Merge "Upgrade path for small/large tiles" into main
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepositoryTest.kt118
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt37
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt52
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSPreferencesInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/domain/startable/QSPanelsCoreStartable.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt13
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeTileSpecRepository.kt7
11 files changed, 306 insertions, 17 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepositoryTest.kt
index 4dcbdfae6d4a..264eda5a07eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepositoryTest.kt
@@ -30,6 +30,7 @@ import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.fakeUserRepository
import com.android.systemui.user.data.repository.userRepository
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -104,6 +105,114 @@ class QSPreferencesRepositoryTest : SysuiTestCase() {
}
}
+ @Test
+ fun setInitialTilesFromSettings_noLargeTiles_tilesSet() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(PRIMARY_USER)
+ val tiles = setOf("tileA", "tileB").toTileSpecs()
+
+ assertThat(getSharedPreferences().contains(LARGE_TILES_SPECS_KEY)).isFalse()
+
+ underTest.setInitialLargeTilesSpecs(tiles, PRIMARY_USER_ID)
+
+ assertThat(largeTiles).isEqualTo(tiles)
+ }
+ }
+
+ @Test
+ fun setInitialTilesFromSettings_alreadyLargeTiles_tilesNotSet() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(ANOTHER_USER)
+ setLargeTilesSpecsInSharedPreferences(setOf("tileC"))
+
+ underTest.setInitialLargeTilesSpecs(setOf("tileA").toTileSpecs(), ANOTHER_USER_ID)
+
+ assertThat(largeTiles).isEqualTo(setOf("tileC").toTileSpecs())
+ }
+ }
+
+ @Test
+ fun setInitialTilesFromSettings_emptyLargeTiles_tilesNotSet() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(ANOTHER_USER)
+ setLargeTilesSpecsInSharedPreferences(emptySet())
+
+ underTest.setInitialLargeTilesSpecs(setOf("tileA").toTileSpecs(), ANOTHER_USER_ID)
+
+ assertThat(largeTiles).isEmpty()
+ }
+ }
+
+ @Test
+ fun setInitialTilesFromSettings_nonCurrentUser_tilesSetForCorrectUser() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(PRIMARY_USER)
+
+ underTest.setInitialLargeTilesSpecs(setOf("tileA").toTileSpecs(), ANOTHER_USER_ID)
+
+ assertThat(largeTiles).isEqualTo(defaultLargeTilesRepository.defaultLargeTiles)
+
+ fakeUserRepository.setSelectedUserInfo(ANOTHER_USER)
+ assertThat(largeTiles).isEqualTo(setOf("tileA").toTileSpecs())
+ }
+ }
+
+ @Test
+ fun setInitialTiles_afterDefaultRead_noSetOnRepository_initialTilesCorrect() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(PRIMARY_USER)
+
+ val currentLargeTiles = underTest.largeTilesSpecs.first()
+
+ assertThat(currentLargeTiles).isNotEmpty()
+
+ val tiles = setOf("tileA", "tileB")
+ underTest.setInitialLargeTilesSpecs(tiles.toTileSpecs(), PRIMARY_USER_ID)
+
+ assertThat(largeTiles).isEqualTo(tiles.toTileSpecs())
+ }
+ }
+
+ @Test
+ fun setInitialTiles_afterDefaultRead_largeTilesSetOnRepository_initialTilesCorrect() =
+ with(kosmos) {
+ testScope.runTest {
+ val largeTiles by collectLastValue(underTest.largeTilesSpecs)
+ fakeUserRepository.setUserInfos(USERS)
+ fakeUserRepository.setSelectedUserInfo(PRIMARY_USER)
+
+ val currentLargeTiles = underTest.largeTilesSpecs.first()
+
+ assertThat(currentLargeTiles).isNotEmpty()
+
+ underTest.setLargeTilesSpecs(setOf(TileSpec.create("tileC")))
+
+ val tiles = setOf("tileA", "tileB")
+ underTest.setInitialLargeTilesSpecs(tiles.toTileSpecs(), PRIMARY_USER_ID)
+
+ assertThat(largeTiles).isEqualTo(setOf(TileSpec.create("tileC")))
+ }
+ }
+
private fun getSharedPreferences(): SharedPreferences =
with(kosmos) {
return userFileManager.getSharedPreferences(
@@ -121,20 +230,11 @@ class QSPreferencesRepositoryTest : SysuiTestCase() {
return getSharedPreferences().getStringSet(LARGE_TILES_SPECS_KEY, emptySet())!!
}
- private fun setShowLabelsInSharedPreferences(value: Boolean) {
- getSharedPreferences().edit().putBoolean(ICON_LABELS_KEY, value).apply()
- }
-
- private fun getShowLabelsFromSharedPreferences(defaultValue: Boolean): Boolean {
- return getSharedPreferences().getBoolean(ICON_LABELS_KEY, defaultValue)
- }
-
private fun Set<String>.toTileSpecs(): Set<TileSpec> {
return map { TileSpec.create(it) }.toSet()
}
companion object {
- private const val ICON_LABELS_KEY = "show_icon_labels"
private const val LARGE_TILES_SPECS_KEY = "large_tiles_specs"
private const val PRIMARY_USER_ID = 0
private val PRIMARY_USER = UserInfo(PRIMARY_USER_ID, "user 0", UserInfo.FLAG_MAIN)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
index 88e3951cdf92..4b8cd3742bff 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
@@ -22,12 +22,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
import com.android.systemui.res.R
import com.android.systemui.retail.data.repository.FakeRetailModeRepository
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -90,6 +92,7 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
logger,
retailModeRepository,
userTileSpecRepositoryFactory,
+ testScope.backgroundScope,
)
}
@@ -231,6 +234,40 @@ class TileSpecSettingsRepositoryTest : SysuiTestCase() {
assertThat(tiles!!).containsExactlyElementsIn(DEFAULT_TILES.toTileSpecs())
}
+ @Test
+ fun readSettingsStored_emittedForUser() =
+ testScope.runTest {
+ val startingTiles = "a,b"
+ val userId = 10
+ storeTilesForUser(startingTiles, userId)
+
+ val tiles by collectLastValue(underTest.tilesSpecs(userId))
+ val tilesRead by collectLastValue(underTest.tilesReadFromSetting.consumeAsFlow())
+
+ assertThat(tilesRead).isEqualTo(startingTiles.toTileSpecs().toSet() to userId)
+ }
+
+ @Test
+ fun readSettingsStored_multipleUsers() =
+ testScope.runTest {
+ val startingTiles10 = "a"
+ val startingTiles11 = "b,c"
+ storeTilesForUser(startingTiles10, 10)
+ storeTilesForUser(startingTiles11, 11)
+
+ val tiles10 by collectLastValue(underTest.tilesSpecs(10))
+ val tiles11 by collectLastValue(underTest.tilesSpecs(11))
+
+ val tilesRead by collectValues(underTest.tilesReadFromSetting.consumeAsFlow())
+
+ assertThat(tilesRead).hasSize(2)
+ assertThat(tilesRead)
+ .containsExactly(
+ startingTiles10.toTileSpecs().toSet() to 10,
+ startingTiles11.toTileSpecs().toSet() to 11,
+ )
+ }
+
private fun TestScope.storeTilesForUser(specs: String, forUser: Int) {
secureSettings.putStringForUser(SETTING, specs, forUser)
runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
index 502e179f62ec..1945f750efaf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
@@ -7,11 +7,13 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.data.model.RestoreData
+import com.android.systemui.qs.pipeline.data.repository.UserTileSpecRepositoryTest.Companion.toTilesSet
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -312,11 +314,7 @@ class UserTileSpecRepositoryTest : SysuiTestCase() {
runCurrent()
val restoreData =
- RestoreData(
- restoredSpecs.toTileSpecs(),
- restoredAutoAdded.toTilesSet(),
- USER,
- )
+ RestoreData(restoredSpecs.toTileSpecs(), restoredAutoAdded.toTilesSet(), USER)
underTest.reconcileRestore(restoreData, autoAddedBeforeRestore.toTilesSet())
runCurrent()
@@ -351,6 +349,49 @@ class UserTileSpecRepositoryTest : SysuiTestCase() {
assertThat(tiles).isEqualTo(currentTiles)
}
+ @Test
+ fun noSettingsStored_noTilesReadFromSettings() =
+ testScope.runTest {
+ val tilesRead by collectLastValue(underTest.tilesReadFromSettings.consumeAsFlow())
+ val tiles by collectLastValue(underTest.tiles())
+
+ assertThat(tiles).isEqualTo(getDefaultTileSpecs())
+ assertThat(tilesRead).isEqualTo(null)
+ }
+
+ @Test
+ fun settingsStored_tilesReadFromSettings() =
+ testScope.runTest {
+ val storedTiles = "a,b"
+ storeTiles(storedTiles)
+ val tiles by collectLastValue(underTest.tiles())
+ val tilesRead by collectLastValue(underTest.tilesReadFromSettings.consumeAsFlow())
+
+ assertThat(tilesRead).isEqualTo(storedTiles.toTilesSet())
+ }
+
+ @Test
+ fun noSettingsStored_tilesChanged_tilesReadFromSettingsNotChanged() =
+ testScope.runTest {
+ val tilesRead by collectLastValue(underTest.tilesReadFromSettings.consumeAsFlow())
+ val tiles by collectLastValue(underTest.tiles())
+
+ underTest.addTile(TileSpec.create("a"))
+ assertThat(tilesRead).isEqualTo(null)
+ }
+
+ @Test
+ fun settingsStored_tilesChanged_tilesReadFromSettingsNotChanged() =
+ testScope.runTest {
+ val storedTiles = "a,b"
+ storeTiles(storedTiles)
+ val tiles by collectLastValue(underTest.tiles())
+ val tilesRead by collectLastValue(underTest.tilesReadFromSettings.consumeAsFlow())
+
+ underTest.addTile(TileSpec.create("c"))
+ assertThat(tilesRead).isEqualTo(storedTiles.toTilesSet())
+ }
+
private fun getDefaultTileSpecs(): List<TileSpec> {
return defaultTilesRepository.defaultTiles
}
@@ -370,6 +411,7 @@ class UserTileSpecRepositoryTest : SysuiTestCase() {
private const val SETTING = Settings.Secure.QS_TILES
private fun String.toTileSpecs() = TilesSettingConverter.toTilesList(this)
+
private fun String.toTilesSet() = TilesSettingConverter.toTilesSet(this)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
index f4bf53cafd19..325c6cafc465 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/dagger/PanelsModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.panels.dagger
+import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
@@ -23,6 +24,7 @@ import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepositor
import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepositoryImpl
import com.android.systemui.qs.panels.domain.interactor.EditTilesResetInteractor
import com.android.systemui.qs.panels.domain.interactor.SizedTilesResetInteractor
+import com.android.systemui.qs.panels.domain.startable.QSPanelsCoreStartable
import com.android.systemui.qs.panels.shared.model.GridLayoutType
import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.shared.model.PaginatedGridLayoutType
@@ -36,6 +38,8 @@ import com.android.systemui.qs.panels.ui.viewmodel.IconTilesViewModelImpl
import dagger.Binds
import dagger.Module
import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
import dagger.multibindings.IntoSet
import javax.inject.Named
@@ -57,6 +61,11 @@ interface PanelsModule {
@Binds @Named("Default") fun bindDefaultGridLayout(impl: PaginatedGridLayout): GridLayout
+ @Binds
+ @IntoMap
+ @ClassKey(QSPanelsCoreStartable::class)
+ fun bindQSPanelsCoreStartable(impl: QSPanelsCoreStartable): CoreStartable
+
companion object {
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
index 19e4fd5b21b0..16dff7d11002 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/data/repository/QSPreferencesRepository.kt
@@ -84,11 +84,33 @@ constructor(
/** Sets for the current user the set of [TileSpec] to display as large tiles. */
fun setLargeTilesSpecs(specs: Set<TileSpec>) {
- with(getSharedPrefs(userRepository.getSelectedUserInfo().id)) {
+ setLargeTilesSpecsForUser(specs, userRepository.getSelectedUserInfo().id)
+ }
+
+ private fun setLargeTilesSpecsForUser(specs: Set<TileSpec>, userId: Int) {
+ with(getSharedPrefs(userId)) {
edit().putStringSet(LARGE_TILES_SPECS_KEY, specs.map { it.spec }.toSet()).apply()
}
}
+ /**
+ * Sets the initial tiles as large, if there is no set in SharedPrefs for the [userId]. This is
+ * to be used when upgrading to a build that supports large/small tiles.
+ *
+ * Even if largeTilesSpec is read Eagerly before we know if we are in an initial state, because
+ * we are not writing the default values to the SharedPreferences, the file will not contain the
+ * key and this call will succeed, as long as there hasn't been any calls to setLargeTilesSpecs
+ * for that user before.
+ */
+ fun setInitialLargeTilesSpecs(specs: Set<TileSpec>, userId: Int) {
+ with(getSharedPrefs(userId)) {
+ if (!contains(LARGE_TILES_SPECS_KEY)) {
+ logger.i("Setting upgraded large tiles for user $userId: $specs")
+ setLargeTilesSpecsForUser(specs, userId)
+ }
+ }
+ }
+
private fun getSharedPrefs(userId: Int): SharedPreferences {
return userFileManager.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE, userId)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
index 23c79f576df5..482cd4014acf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/IconTilesInteractor.kt
@@ -44,6 +44,7 @@ constructor(
@PanelsLog private val logBuffer: LogBuffer,
@Application private val applicationScope: CoroutineScope,
) {
+
val largeTilesSpecs =
preferencesInteractor.largeTilesSpecs
.onEach { logChange(it) }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSPreferencesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSPreferencesInteractor.kt
index 22543b12b93c..86838b438bc6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSPreferencesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/interactor/QSPreferencesInteractor.kt
@@ -29,4 +29,8 @@ class QSPreferencesInteractor @Inject constructor(private val repo: QSPreference
fun setLargeTilesSpecs(specs: Set<TileSpec>) {
repo.setLargeTilesSpecs(specs)
}
+
+ fun setInitialLargeTilesSpecs(specs: Set<TileSpec>, user: Int) {
+ repo.setInitialLargeTilesSpecs(specs, user)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/domain/startable/QSPanelsCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/startable/QSPanelsCoreStartable.kt
new file mode 100644
index 000000000000..a8ac5c34d8f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/domain/startable/QSPanelsCoreStartable.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2025 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.panels.domain.startable
+
+import com.android.app.tracing.coroutines.launchTraced
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.panels.domain.interactor.QSPreferencesInteractor
+import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.receiveAsFlow
+
+class QSPanelsCoreStartable
+@Inject
+constructor(
+ private val tileSpecRepository: TileSpecRepository,
+ private val preferenceInteractor: QSPreferencesInteractor,
+ @Background private val backgroundApplicationScope: CoroutineScope,
+) : CoreStartable {
+ override fun start() {
+ backgroundApplicationScope.launchTraced("QSPanelsCoreStartable.startingLargeTiles") {
+ tileSpecRepository.tilesReadFromSetting.receiveAsFlow().collect { (tiles, userId) ->
+ preferenceInteractor.setInitialLargeTilesSpecs(tiles, userId)
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
index 4e993786e343..6b7dd386bb46 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TileSpecRepository.kt
@@ -19,7 +19,9 @@ package com.android.systemui.qs.pipeline.data.repository
import android.annotation.UserIdInt
import android.content.res.Resources
import android.util.SparseArray
+import com.android.app.tracing.coroutines.launchTraced
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.qs.pipeline.shared.logging.QSPipelineLogger
@@ -27,6 +29,9 @@ import com.android.systemui.res.R
import com.android.systemui.retail.data.repository.RetailModeRepository
import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -73,6 +78,8 @@ interface TileSpecRepository {
/** Reset the current set of tiles to the default list of tiles */
suspend fun resetToDefault(userId: Int)
+ val tilesReadFromSetting: ReceiveChannel<Pair<Set<TileSpec>, Int>>
+
companion object {
/** Position to indicate the end of the list */
const val POSITION_AT_END = -1
@@ -94,6 +101,7 @@ constructor(
private val logger: QSPipelineLogger,
private val retailModeRepository: RetailModeRepository,
private val userTileSpecRepositoryFactory: UserTileSpecRepository.Factory,
+ @Background private val applicationScope: CoroutineScope,
) : TileSpecRepository {
private val retailModeTiles by lazy {
@@ -104,12 +112,20 @@ constructor(
.filter { it !is TileSpec.Invalid }
}
+ private val _tilesReadFromSetting = Channel<Pair<Set<TileSpec>, Int>>(capacity = 5)
+ override val tilesReadFromSetting = _tilesReadFromSetting
+
private val userTileRepositories = SparseArray<UserTileSpecRepository>()
override suspend fun tilesSpecs(userId: Int): Flow<List<TileSpec>> {
if (userId !in userTileRepositories) {
val userTileRepository = userTileSpecRepositoryFactory.create(userId)
userTileRepositories.put(userId, userTileRepository)
+ applicationScope.launchTraced("TileSpecRepository.aggregateTilesPerUser") {
+ for (tilesFromSettings in userTileRepository.tilesReadFromSettings) {
+ _tilesReadFromSetting.send(tilesFromSettings to userId)
+ }
+ }
}
val realTiles = userTileRepositories.get(userId).tiles()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt
index 64da853484ff..7b56cd92a081 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt
@@ -3,6 +3,7 @@ package com.android.systemui.qs.pipeline.data.repository
import android.annotation.UserIdInt
import android.database.ContentObserver
import android.provider.Settings
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.common.coroutine.ConflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
@@ -15,6 +16,8 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -23,7 +26,6 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
import kotlinx.coroutines.withContext
/**
@@ -47,6 +49,9 @@ constructor(
@Background private val backgroundDispatcher: CoroutineDispatcher,
) {
+ private val _tilesReadFromSettings = Channel<Set<TileSpec>>(capacity = 2)
+ val tilesReadFromSettings: ReceiveChannel<Set<TileSpec>> = _tilesReadFromSettings
+
private val defaultTiles: List<TileSpec>
get() = defaultTilesRepository.defaultTiles
@@ -147,7 +152,11 @@ constructor(
}
private suspend fun loadTilesFromSettingsAndParse(userId: Int): List<TileSpec> {
- return parseTileSpecs(loadTilesFromSettings(userId), userId)
+ val loadedTiles = loadTilesFromSettings(userId)
+ if (loadedTiles.isNotEmpty()) {
+ _tilesReadFromSettings.send(loadedTiles.toSet())
+ }
+ return parseTileSpecs(loadedTiles, userId)
}
private suspend fun loadTilesFromSettings(userId: Int): List<TileSpec> {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeTileSpecRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeTileSpecRepository.kt
index 1c69eab9602e..5fc31f8b9e10 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeTileSpecRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeTileSpecRepository.kt
@@ -19,6 +19,7 @@ package com.android.systemui.qs.pipeline.data.repository
import com.android.systemui.qs.pipeline.data.model.RestoreData
import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository.Companion.POSITION_AT_END
import com.android.systemui.qs.pipeline.shared.TileSpec
+import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -77,4 +78,10 @@ class FakeTileSpecRepository(
override suspend fun resetToDefault(userId: Int) {
with(getFlow(userId)) { value = defaultTilesRepository.defaultTiles }
}
+
+ override val tilesReadFromSetting: Channel<Pair<Set<TileSpec>, Int>> = Channel(capacity = 10)
+
+ suspend fun sendTilesReadFromSetting(tiles: Set<TileSpec>, userId: Int) {
+ tilesReadFromSetting.send(tiles to userId)
+ }
}