Add a AutoAddInteractor
This is meant to replace the old AutoTileManager. It works with a
collection of AutoAddable, so adding new rules for tiles that need to be
added is easier to do.
Fixes: 278577795
Test: atest com.android.systemui.qs.pipeline
Flag: QS_PIPELINE_AUTO_ADD
Change-Id: Iee7e70f90034c5bb773a515660f88548d5a0aa86
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index d2568ac..bc4d774 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -161,7 +161,9 @@
// finishes before creating any tiles.
tunerService.addTunable(this, TILES_SETTING);
// AutoTileManager can modify mTiles so make sure mTiles has already been initialized.
- mAutoTiles = autoTiles.get();
+ if (!mFeatureFlags.isEnabled(Flags.QS_PIPELINE_AUTO_ADD)) {
+ mAutoTiles = autoTiles.get();
+ }
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddLog.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddLog.kt
new file mode 100644
index 0000000..91cb5bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddLog.kt
@@ -0,0 +1,22 @@
+/*
+ * 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 javax.inject.Qualifier
+
+/** A [LogBuffer] for the QS pipeline to track auto-added tiles */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class QSAutoAddLog
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddModule.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddModule.kt
index 99792286..a010ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSAutoAddModule.kt
@@ -16,13 +16,40 @@
package com.android.systemui.qs.pipeline.dagger
+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.AutoAddRepository
import com.android.systemui.qs.pipeline.data.repository.AutoAddSettingRepository
+import com.android.systemui.qs.pipeline.domain.model.AutoAddable
+import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
import dagger.Binds
import dagger.Module
+import dagger.Provides
+import dagger.multibindings.Multibinds
-@Module
+@Module(
+ includes =
+ [
+ BaseAutoAddableModule::class,
+ ]
+)
abstract class QSAutoAddModule {
@Binds abstract fun bindAutoAddRepository(impl: AutoAddSettingRepository): AutoAddRepository
+
+ @Multibinds abstract fun providesAutoAddableSet(): Set<AutoAddable>
+
+ companion object {
+ /**
+ * Provides a logging buffer for all logs related to the new Quick Settings pipeline to log
+ * auto added tiles.
+ */
+ @Provides
+ @SysUISingleton
+ @QSAutoAddLog
+ fun provideQSAutoAddLogBuffer(factory: LogBufferFactory): LogBuffer {
+ return factory.create(QSPipelineLogger.AUTO_ADD_TAG, maxSize = 100, systrace = false)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSTileListLog.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSTileListLog.kt
index ad8bfea..c56ca8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSTileListLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSTileListLog.kt
@@ -19,5 +19,5 @@
import java.lang.annotation.RetentionPolicy
import javax.inject.Qualifier
-/** A {@link LogBuffer} for the new QS Pipeline for logging changes to the set of current tiles. */
+/** A [LogBuffer] for the new QS Pipeline for logging changes to the set of current tiles. */
@Qualifier @MustBeDocumented @Retention(RetentionPolicy.RUNTIME) annotation class QSTileListLog
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt
new file mode 100644
index 0000000..b747393
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractor.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.domain.interactor
+
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.qs.pipeline.data.repository.AutoAddRepository
+import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
+import com.android.systemui.qs.pipeline.domain.model.AutoAddTracking
+import com.android.systemui.qs.pipeline.domain.model.AutoAddable
+import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.indentIfPossible
+import java.io.PrintWriter
+import java.util.concurrent.atomic.AtomicBoolean
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filterIsInstance
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.launch
+
+/**
+ * Collects the signals coming from all registered [AutoAddable] and adds/removes tiles accordingly.
+ */
+@SysUISingleton
+class AutoAddInteractor
+@Inject
+constructor(
+ private val autoAddables: Set<@JvmSuppressWildcards AutoAddable>,
+ private val repository: AutoAddRepository,
+ private val dumpManager: DumpManager,
+ private val qsPipelineLogger: QSPipelineLogger,
+ @Application private val scope: CoroutineScope,
+) : Dumpable {
+
+ private val initialized = AtomicBoolean(false)
+
+ /** Start collection of signals following the user from [currentTilesInteractor]. */
+ fun init(currentTilesInteractor: CurrentTilesInteractor) {
+ if (!initialized.compareAndSet(false, true)) {
+ return
+ }
+
+ dumpManager.registerNormalDumpable(TAG, this)
+
+ scope.launch {
+ currentTilesInteractor.userId.collectLatest { userId ->
+ coroutineScope {
+ val previouslyAdded = repository.autoAddedTiles(userId).stateIn(this)
+
+ autoAddables
+ .map { addable ->
+ val autoAddSignal = addable.autoAddSignal(userId)
+ when (val lifecycle = addable.autoAddTracking) {
+ is AutoAddTracking.Always -> autoAddSignal
+ is AutoAddTracking.Disabled -> emptyFlow()
+ is AutoAddTracking.IfNotAdded -> {
+ if (lifecycle.spec !in previouslyAdded.value) {
+ autoAddSignal.filterIsInstance<AutoAddSignal.Add>().take(1)
+ } else {
+ emptyFlow()
+ }
+ }
+ }
+ }
+ .merge()
+ .collect { signal ->
+ when (signal) {
+ is AutoAddSignal.Add -> {
+ if (signal.spec !in previouslyAdded.value) {
+ currentTilesInteractor.addTile(signal.spec, signal.position)
+ qsPipelineLogger.logTileAutoAdded(
+ userId,
+ signal.spec,
+ signal.position
+ )
+ repository.markTileAdded(userId, signal.spec)
+ }
+ }
+ is AutoAddSignal.Remove -> {
+ currentTilesInteractor.removeTiles(setOf(signal.spec))
+ qsPipelineLogger.logTileAutoRemoved(userId, signal.spec)
+ repository.unmarkTileAdded(userId, signal.spec)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ with(pw.asIndenting()) {
+ println("AutoAddables:")
+ indentIfPossible { autoAddables.forEach { println(it.description) } }
+ }
+ }
+
+ companion object {
+ private const val TAG = "AutoAddInteractor"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
index ff881f7..81b682a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
@@ -125,6 +125,7 @@
class CurrentTilesInteractorImpl
@Inject
constructor(
+ autoAddInteractor: AutoAddInteractor,
private val tileSpecRepository: TileSpecRepository,
private val installedTilesComponentRepository: InstalledTilesComponentRepository,
private val userRepository: UserRepository,
@@ -172,6 +173,10 @@
if (featureFlags.isEnabled(Flags.QS_PIPELINE_NEW_HOST)) {
startTileCollection()
}
+
+ if (featureFlags.isEnabled(Flags.QS_PIPELINE_AUTO_ADD)) {
+ autoAddInteractor.init(this)
+ }
}
@OptIn(ExperimentalCoroutinesApi::class)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
index 8318ec9..d400faa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
@@ -19,6 +19,7 @@
import android.annotation.UserIdInt
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
+import com.android.systemui.qs.pipeline.dagger.QSAutoAddLog
import com.android.systemui.qs.pipeline.dagger.QSTileListLog
import com.android.systemui.qs.pipeline.shared.TileSpec
import javax.inject.Inject
@@ -32,10 +33,12 @@
@Inject
constructor(
@QSTileListLog private val tileListLogBuffer: LogBuffer,
+ @QSAutoAddLog private val tileAutoAddLogBuffer: LogBuffer,
) {
companion object {
const val TILE_LIST_TAG = "QSTileListLog"
+ const val AUTO_ADD_TAG = "QSAutoAddableLog"
}
/**
@@ -136,6 +139,31 @@
)
}
+ fun logTileAutoAdded(userId: Int, spec: TileSpec, position: Int) {
+ tileAutoAddLogBuffer.log(
+ AUTO_ADD_TAG,
+ LogLevel.DEBUG,
+ {
+ int1 = userId
+ int2 = position
+ str1 = spec.toString()
+ },
+ { "Tile $str1 auto added for user $int1 at position $int2" }
+ )
+ }
+
+ fun logTileAutoRemoved(userId: Int, spec: TileSpec) {
+ tileAutoAddLogBuffer.log(
+ AUTO_ADD_TAG,
+ LogLevel.DEBUG,
+ {
+ int1 = userId
+ str1 = spec.toString()
+ },
+ { "Tile $str1 auto removed for user $int1" }
+ )
+ }
+
/** Reasons for destroying an existing tile. */
enum class TileDestroyedReason(val readable: String) {
TILE_REMOVED("Tile removed from current set"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index d98bcee..cc42f5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -140,6 +140,7 @@
mFeatureFlags = new FakeFeatureFlags();
mFeatureFlags.set(Flags.QS_PIPELINE_NEW_HOST, false);
+ mFeatureFlags.set(Flags.QS_PIPELINE_AUTO_ADD, false);
mMainExecutor = new FakeExecutor(new FakeSystemClock());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
new file mode 100644
index 0000000..f924b35
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
@@ -0,0 +1,201 @@
+/*
+ * 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.domain.interactor
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.qs.pipeline.data.repository.FakeAutoAddRepository
+import com.android.systemui.qs.pipeline.domain.autoaddable.FakeAutoAddable
+import com.android.systemui.qs.pipeline.domain.model.AutoAddTracking
+import com.android.systemui.qs.pipeline.domain.model.AutoAddable
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.pipeline.shared.logging.QSPipelineLogger
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class AutoAddInteractorTest : SysuiTestCase() {
+ private val testScope = TestScope()
+
+ private val autoAddRepository = FakeAutoAddRepository()
+
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var currentTilesInteractor: CurrentTilesInteractor
+ @Mock private lateinit var logger: QSPipelineLogger
+ private lateinit var underTest: AutoAddInteractor
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(currentTilesInteractor.userId).thenReturn(MutableStateFlow(USER))
+ }
+
+ @Test
+ fun autoAddable_alwaysTrack_addSignal_tileAddedAndMarked() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.Always)
+ val autoAddedTiles by collectLastValue(autoAddRepository.autoAddedTiles(USER))
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ val position = 3
+ fakeAutoAddable.sendAddSignal(USER, position)
+ runCurrent()
+
+ verify(currentTilesInteractor).addTile(SPEC, position)
+ assertThat(autoAddedTiles).contains(SPEC)
+ }
+
+ @Test
+ fun autoAddable_alwaysTrack_addThenRemoveSignal_tileAddedAndRemoved() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.Always)
+ val autoAddedTiles by collectLastValue(autoAddRepository.autoAddedTiles(USER))
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ val position = 3
+ fakeAutoAddable.sendAddSignal(USER, position)
+ runCurrent()
+ fakeAutoAddable.sendRemoveSignal(USER)
+ runCurrent()
+
+ val inOrder = inOrder(currentTilesInteractor)
+ inOrder.verify(currentTilesInteractor).addTile(SPEC, position)
+ inOrder.verify(currentTilesInteractor).removeTiles(setOf(SPEC))
+ assertThat(autoAddedTiles).doesNotContain(SPEC)
+ }
+
+ @Test
+ fun autoAddable_alwaysTrack_addSignalWhenAddedPreviously_noop() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.Always)
+ autoAddRepository.markTileAdded(USER, SPEC)
+ runCurrent()
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ val position = 3
+ fakeAutoAddable.sendAddSignal(USER, position)
+ runCurrent()
+
+ verify(currentTilesInteractor, never()).addTile(SPEC, position)
+ }
+
+ @Test
+ fun autoAddable_disabled_noInteractionsWithCurrentTilesInteractor() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.Disabled)
+ val autoAddedTiles by collectLastValue(autoAddRepository.autoAddedTiles(USER))
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ val position = 3
+ fakeAutoAddable.sendAddSignal(USER, position)
+ runCurrent()
+ fakeAutoAddable.sendRemoveSignal(USER)
+ runCurrent()
+
+ verify(currentTilesInteractor, never()).addTile(any(), anyInt())
+ verify(currentTilesInteractor, never()).removeTiles(any())
+ assertThat(autoAddedTiles).doesNotContain(SPEC)
+ }
+
+ @Test
+ fun autoAddable_trackIfNotAdded_removeSignal_noop() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.IfNotAdded(SPEC))
+ runCurrent()
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ fakeAutoAddable.sendRemoveSignal(USER)
+ runCurrent()
+
+ verify(currentTilesInteractor, never()).addTile(any(), anyInt())
+ verify(currentTilesInteractor, never()).removeTiles(any())
+ }
+
+ @Test
+ fun autoAddable_trackIfNotAdded_addSignalWhenPreviouslyAdded_noop() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.IfNotAdded(SPEC))
+ autoAddRepository.markTileAdded(USER, SPEC)
+ runCurrent()
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ fakeAutoAddable.sendAddSignal(USER)
+ runCurrent()
+
+ verify(currentTilesInteractor, never()).addTile(any(), anyInt())
+ verify(currentTilesInteractor, never()).removeTiles(any())
+ }
+
+ @Test
+ fun autoAddable_trackIfNotAdded_addSignal_addedAndMarked() =
+ testScope.runTest {
+ val fakeAutoAddable = FakeAutoAddable(SPEC, AutoAddTracking.IfNotAdded(SPEC))
+ val autoAddedTiles by collectLastValue(autoAddRepository.autoAddedTiles(USER))
+
+ underTest = createInteractor(setOf(fakeAutoAddable))
+
+ val position = 3
+ fakeAutoAddable.sendAddSignal(USER, position)
+ runCurrent()
+
+ verify(currentTilesInteractor).addTile(SPEC, position)
+ assertThat(autoAddedTiles).contains(SPEC)
+ }
+
+ private fun createInteractor(autoAddables: Set<AutoAddable>): AutoAddInteractor {
+ return AutoAddInteractor(
+ autoAddables,
+ autoAddRepository,
+ dumpManager,
+ logger,
+ testScope.backgroundScope
+ )
+ .apply { init(currentTilesInteractor) }
+ }
+
+ companion object {
+ private val SPEC = TileSpec.create("spec")
+ private val USER = 10
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
index e7ad489..522ffc1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
@@ -83,6 +83,8 @@
@Mock private lateinit var customTileStatePersister: CustomTileStatePersister
+ @Mock private lateinit var autoAddInteractor: AutoAddInteractor
+
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var logger: QSPipelineLogger
@@ -100,6 +102,7 @@
MockitoAnnotations.initMocks(this)
featureFlags.set(Flags.QS_PIPELINE_NEW_HOST, true)
+ featureFlags.set(Flags.QS_PIPELINE_AUTO_ADD, true)
userRepository.setUserInfos(listOf(USER_INFO_0, USER_INFO_1))
@@ -107,6 +110,7 @@
underTest =
CurrentTilesInteractorImpl(
+ autoAddInteractor = autoAddInteractor,
tileSpecRepository = tileSpecRepository,
installedTilesComponentRepository = installedTilesPackageRepository,
userRepository = userRepository,
@@ -647,6 +651,11 @@
assertThat(tiles!![1].spec).isEqualTo(CUSTOM_TILE_SPEC)
}
+ @Test
+ fun autoAddInteractor_initted() {
+ verify(autoAddInteractor).init(underTest)
+ }
+
private fun QSTile.State.fillIn(state: Int, label: CharSequence, secondaryLabel: CharSequence) {
this.state = state
this.label = label
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeAutoAddRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeAutoAddRepository.kt
new file mode 100644
index 0000000..9ea079f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/pipeline/data/repository/FakeAutoAddRepository.kt
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.systemui.qs.pipeline.shared.TileSpec
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeAutoAddRepository : AutoAddRepository {
+
+ private val autoAddedTilesPerUser = mutableMapOf<Int, MutableStateFlow<Set<TileSpec>>>()
+
+ override fun autoAddedTiles(userId: Int): Flow<Set<TileSpec>> {
+ return getFlow(userId)
+ }
+
+ override suspend fun markTileAdded(userId: Int, spec: TileSpec) {
+ if (spec == TileSpec.Invalid) return
+ with(getFlow(userId)) { value = value.toMutableSet().apply { add(spec) } }
+ }
+
+ override suspend fun unmarkTileAdded(userId: Int, spec: TileSpec) {
+ with(getFlow(userId)) { value = value.toMutableSet().apply { remove(spec) } }
+ }
+
+ private fun getFlow(userId: Int): MutableStateFlow<Set<TileSpec>> =
+ autoAddedTilesPerUser.getOrPut(userId) { MutableStateFlow(emptySet()) }
+}