Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,8 @@ class QSTileViewModelTest : SysuiTestCase() { runCurrent() assertThat(states()).isNotEmpty() assertThat(states().first().label).isEqualTo(testTileData) assertThat(states().last()).isNotNull() assertThat(states().last()!!.label).isEqualTo(testTileData) verify(qsTileLogger).logInitialRequest(eq(tileConfig.tileSpec)) } Loading Loading @@ -196,6 +197,7 @@ class QSTileViewModelTest : SysuiTestCase() { qsTileLogger, FakeSystemClock(), testCoroutineDispatcher, testCoroutineDispatcher, scope.backgroundScope, ) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ class QSTileViewModelUserInputTest : SysuiTestCase() { qsTileLogger, FakeSystemClock(), testCoroutineDispatcher, testCoroutineDispatcher, scope.backgroundScope, ) } packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles.base.viewmodel import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.UiBackground import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics Loading Loading @@ -61,6 +62,7 @@ sealed interface QSTileViewModelFactory<T> { private val qsTileConfigProvider: QSTileConfigProvider, private val systemClock: SystemClock, @Background private val backgroundDispatcher: CoroutineDispatcher, @UiBackground private val uiBackgroundDispatcher: CoroutineDispatcher, private val customTileComponentBuilder: CustomTileComponent.Builder, ) : QSTileViewModelFactory<CustomTileDataModel> { Loading @@ -86,6 +88,7 @@ sealed interface QSTileViewModelFactory<T> { qsTileLogger, systemClock, backgroundDispatcher, uiBackgroundDispatcher, component.coroutineScope(), ) } Loading @@ -106,6 +109,7 @@ sealed interface QSTileViewModelFactory<T> { private val qsTileConfigProvider: QSTileConfigProvider, private val systemClock: SystemClock, @Background private val backgroundDispatcher: CoroutineDispatcher, @UiBackground private val uiBackgroundDispatcher: CoroutineDispatcher, private val coroutineScopeFactory: QSTileCoroutineScopeFactory, ) : QSTileViewModelFactory<T> { Loading Loading @@ -136,6 +140,7 @@ sealed interface QSTileViewModelFactory<T> { qsTileLogger, systemClock, backgroundDispatcher, uiBackgroundDispatcher, coroutineScopeFactory.create(), ) } Loading packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt +29 −27 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -59,7 +60,9 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Provides a hassle-free way to implement new tiles according to current System UI architecture Loading @@ -81,6 +84,7 @@ class QSTileViewModelImpl<DATA_TYPE>( private val qsTileLogger: QSTileLogger, private val systemClock: SystemClock, private val backgroundDispatcher: CoroutineDispatcher, uiBackgroundDispatcher: CoroutineDispatcher, private val tileScope: CoroutineScope, ) : QSTileViewModel, Dumpable { Loading @@ -93,18 +97,16 @@ class QSTileViewModelImpl<DATA_TYPE>( private val tileData: SharedFlow<DATA_TYPE> = createTileDataFlow() override val state: SharedFlow<QSTileState> = override val state: StateFlow<QSTileState?> = tileData .map { data -> mapper().map(config, data).also { state -> qsTileLogger.logStateUpdate(spec, state, data) withContext(uiBackgroundDispatcher) { mapper().map(config, data) } .also { state -> qsTileLogger.logStateUpdate(spec, state, data) } } } .flowOn(backgroundDispatcher) .shareIn( .stateIn( tileScope, SharingStarted.WhileSubscribed(), replay = 1, null, ) override val isAvailable: StateFlow<Boolean> = users Loading Loading @@ -147,26 +149,26 @@ class QSTileViewModelImpl<DATA_TYPE>( private fun createTileDataFlow(): SharedFlow<DATA_TYPE> = users .flatMapLatest { user -> val updateTriggers = .transformLatest { user -> coroutineScope { val updateTriggers: Flow<DataUpdateTrigger> = merge( userInputFlow(user), forceUpdates .map { DataUpdateTrigger.ForceUpdate } .onEach { qsTileLogger.logForceUpdate(spec) }, ) .onStart { emit(DataUpdateTrigger.InitialRequest) qsTileLogger.logInitialRequest(spec) } .shareIn(tileScope, SharingStarted.WhileSubscribed()) .onStart { qsTileLogger.logInitialRequest(spec) } .stateIn(this, SharingStarted.Eagerly, DataUpdateTrigger.InitialRequest) tileDataInteractor() .tileData(user, updateTriggers) // combine makes sure updateTriggers is always listened even if // tileDataInteractor#tileData doesn't flatMapLatest on it // tileDataInteractor#tileData doesn't transformLatest on it .combine(updateTriggers) { data, _ -> data } .cancellable() .flowOn(backgroundDispatcher) .collect { emit(it) } } } .distinctUntilChanged() .shareIn( Loading packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/domain/interactor/QRCodeScannerTileDataInteractor.kt +0 −7 Original line number Diff line number Diff line Loading @@ -30,11 +30,9 @@ import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn /** Observes one qr scanner state changes providing the [QRCodeScannerTileModel]. */ class QRCodeScannerTileDataInteractor Loading Loading @@ -66,11 +64,6 @@ constructor( } .onStart { emit(generateModel()) } .flowOn(bgCoroutineContext) .stateIn( scope, SharingStarted.WhileSubscribed(), QRCodeScannerTileModel.TemporarilyUnavailable ) override fun availability(user: UserHandle): Flow<Boolean> = flowOf(qrController.isCameraAvailable) Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelTest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,8 @@ class QSTileViewModelTest : SysuiTestCase() { runCurrent() assertThat(states()).isNotEmpty() assertThat(states().first().label).isEqualTo(testTileData) assertThat(states().last()).isNotNull() assertThat(states().last()!!.label).isEqualTo(testTileData) verify(qsTileLogger).logInitialRequest(eq(tileConfig.tileSpec)) } Loading Loading @@ -196,6 +197,7 @@ class QSTileViewModelTest : SysuiTestCase() { qsTileLogger, FakeSystemClock(), testCoroutineDispatcher, testCoroutineDispatcher, scope.backgroundScope, ) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelUserInputTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ class QSTileViewModelUserInputTest : SysuiTestCase() { qsTileLogger, FakeSystemClock(), testCoroutineDispatcher, testCoroutineDispatcher, scope.backgroundScope, ) }
packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelFactory.kt +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles.base.viewmodel import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.UiBackground import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics Loading Loading @@ -61,6 +62,7 @@ sealed interface QSTileViewModelFactory<T> { private val qsTileConfigProvider: QSTileConfigProvider, private val systemClock: SystemClock, @Background private val backgroundDispatcher: CoroutineDispatcher, @UiBackground private val uiBackgroundDispatcher: CoroutineDispatcher, private val customTileComponentBuilder: CustomTileComponent.Builder, ) : QSTileViewModelFactory<CustomTileDataModel> { Loading @@ -86,6 +88,7 @@ sealed interface QSTileViewModelFactory<T> { qsTileLogger, systemClock, backgroundDispatcher, uiBackgroundDispatcher, component.coroutineScope(), ) } Loading @@ -106,6 +109,7 @@ sealed interface QSTileViewModelFactory<T> { private val qsTileConfigProvider: QSTileConfigProvider, private val systemClock: SystemClock, @Background private val backgroundDispatcher: CoroutineDispatcher, @UiBackground private val uiBackgroundDispatcher: CoroutineDispatcher, private val coroutineScopeFactory: QSTileCoroutineScopeFactory, ) : QSTileViewModelFactory<T> { Loading Loading @@ -136,6 +140,7 @@ sealed interface QSTileViewModelFactory<T> { qsTileLogger, systemClock, backgroundDispatcher, uiBackgroundDispatcher, coroutineScopeFactory.create(), ) } Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt +29 −27 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -59,7 +60,9 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext /** * Provides a hassle-free way to implement new tiles according to current System UI architecture Loading @@ -81,6 +84,7 @@ class QSTileViewModelImpl<DATA_TYPE>( private val qsTileLogger: QSTileLogger, private val systemClock: SystemClock, private val backgroundDispatcher: CoroutineDispatcher, uiBackgroundDispatcher: CoroutineDispatcher, private val tileScope: CoroutineScope, ) : QSTileViewModel, Dumpable { Loading @@ -93,18 +97,16 @@ class QSTileViewModelImpl<DATA_TYPE>( private val tileData: SharedFlow<DATA_TYPE> = createTileDataFlow() override val state: SharedFlow<QSTileState> = override val state: StateFlow<QSTileState?> = tileData .map { data -> mapper().map(config, data).also { state -> qsTileLogger.logStateUpdate(spec, state, data) withContext(uiBackgroundDispatcher) { mapper().map(config, data) } .also { state -> qsTileLogger.logStateUpdate(spec, state, data) } } } .flowOn(backgroundDispatcher) .shareIn( .stateIn( tileScope, SharingStarted.WhileSubscribed(), replay = 1, null, ) override val isAvailable: StateFlow<Boolean> = users Loading Loading @@ -147,26 +149,26 @@ class QSTileViewModelImpl<DATA_TYPE>( private fun createTileDataFlow(): SharedFlow<DATA_TYPE> = users .flatMapLatest { user -> val updateTriggers = .transformLatest { user -> coroutineScope { val updateTriggers: Flow<DataUpdateTrigger> = merge( userInputFlow(user), forceUpdates .map { DataUpdateTrigger.ForceUpdate } .onEach { qsTileLogger.logForceUpdate(spec) }, ) .onStart { emit(DataUpdateTrigger.InitialRequest) qsTileLogger.logInitialRequest(spec) } .shareIn(tileScope, SharingStarted.WhileSubscribed()) .onStart { qsTileLogger.logInitialRequest(spec) } .stateIn(this, SharingStarted.Eagerly, DataUpdateTrigger.InitialRequest) tileDataInteractor() .tileData(user, updateTriggers) // combine makes sure updateTriggers is always listened even if // tileDataInteractor#tileData doesn't flatMapLatest on it // tileDataInteractor#tileData doesn't transformLatest on it .combine(updateTriggers) { data, _ -> data } .cancellable() .flowOn(backgroundDispatcher) .collect { emit(it) } } } .distinctUntilChanged() .shareIn( Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/domain/interactor/QRCodeScannerTileDataInteractor.kt +0 −7 Original line number Diff line number Diff line Loading @@ -30,11 +30,9 @@ import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn /** Observes one qr scanner state changes providing the [QRCodeScannerTileModel]. */ class QRCodeScannerTileDataInteractor Loading Loading @@ -66,11 +64,6 @@ constructor( } .onStart { emit(generateModel()) } .flowOn(bgCoroutineContext) .stateIn( scope, SharingStarted.WhileSubscribed(), QRCodeScannerTileModel.TemporarilyUnavailable ) override fun availability(user: UserHandle): Flow<Boolean> = flowOf(qrController.isCameraAvailable) Loading