Loading packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt +13 −9 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -47,6 +46,8 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn Loading @@ -57,6 +58,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** * Provides a hassle-free way to implement new tiles according to current System UI architecture Loading @@ -83,10 +85,8 @@ class QSTileViewModelImpl<DATA_TYPE>( private val users: MutableStateFlow<UserHandle> = MutableStateFlow(userRepository.getSelectedUserInfo().userHandle) private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow() private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow() private val spec get() = config.tileSpec Loading Loading @@ -130,7 +130,7 @@ class QSTileViewModelImpl<DATA_TYPE>( tileData.replayCache.isNotEmpty(), state.replayCache.isNotEmpty() ) userInputs.tryEmit(userAction) tileScope.launch { userInputs.emit(userAction) } } override fun destroy() { Loading @@ -151,11 +151,16 @@ class QSTileViewModelImpl<DATA_TYPE>( emit(DataUpdateTrigger.InitialRequest) qsTileLogger.logInitialRequest(spec) } .shareIn(tileScope, SharingStarted.WhileSubscribed()) tileDataInteractor() .tileData(user, updateTriggers) // combine makes sure updateTriggers is always listened even if // tileDataInteractor#tileData doesn't flatMapLatest on it .combine(updateTriggers) { data, _ -> data } .cancellable() .flowOn(backgroundDispatcher) } .distinctUntilChanged() .shareIn( tileScope, SharingStarted.WhileSubscribed(), Loading @@ -171,8 +176,8 @@ class QSTileViewModelImpl<DATA_TYPE>( * * Subscribing to the result flow twice will result in doubling all actions, logs and analytics. */ private fun userInputFlow(user: UserHandle): Flow<DataUpdateTrigger> { return userInputs private fun userInputFlow(user: UserHandle): Flow<DataUpdateTrigger> = userInputs .filterFalseActions() .filterByPolicy(user) .throttle(CLICK_THROTTLE_DURATION, systemClock) Loading @@ -187,7 +192,6 @@ class QSTileViewModelImpl<DATA_TYPE>( } .onEach { userActionInteractor().handleInput(it.input) } .flowOn(backgroundDispatcher) } private fun Flow<QSTileUserAction>.filterByPolicy(user: UserHandle): Flow<QSTileUserAction> = config.policy.let { policy -> Loading packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt +6 −6 Original line number Diff line number Diff line Loading @@ -36,9 +36,9 @@ data class QSTileConfig( */ sealed interface QSTileUIConfig { val tileIconRes: Int val iconRes: Int @DrawableRes get val tileLabelRes: Int val labelRes: Int @StringRes get /** Loading @@ -46,16 +46,16 @@ sealed interface QSTileUIConfig { * of [Resource]. Returns [Resources.ID_NULL] for each field. */ data object Empty : QSTileUIConfig { override val tileIconRes: Int override val iconRes: Int get() = Resources.ID_NULL override val tileLabelRes: Int override val labelRes: Int get() = Resources.ID_NULL } /** Config containing actual icon and label resources. */ data class Resource( @StringRes override val tileIconRes: Int, @StringRes override val tileLabelRes: Int, @DrawableRes override val iconRes: Int, @StringRes override val labelRes: Int, ) : QSTileUIConfig } Loading packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt +12 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.qs.tiles.viewmodel import android.content.Context import android.service.quicksettings.Tile import com.android.systemui.common.shared.model.Icon Loading @@ -41,11 +42,19 @@ data class QSTileState( companion object { fun build( context: Context, config: QSTileUIConfig, build: Builder.() -> Unit ): QSTileState = build( { Icon.Resource(config.iconRes, null) }, context.getString(config.labelRes), build, ) fun build(icon: () -> Icon, label: CharSequence, build: Builder.() -> Unit): QSTileState = Builder(icon, label).apply(build).build() fun build(icon: Icon, label: CharSequence, build: Builder.() -> Unit): QSTileState = build({ icon }, label, build) } enum class ActivationState(val legacyState: Int) { Loading packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt +1 −1 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ constructor( with(qsTileViewModel.config.uiConfig) { when (this) { is QSTileUIConfig.Empty -> qsTileViewModel.currentState?.label ?: "" is QSTileUIConfig.Resource -> context.getString(tileLabelRes) is QSTileUIConfig.Resource -> context.getString(labelRes) } } Loading packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt +2 −2 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ class QSTileLoggerTest : SysuiTestCase() { underTest.logUserActionPipeline( TileSpec.create("test_spec"), QSTileUserAction.Click(null), QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {}, QSTileState.build({ Icon.Resource(0, ContentDescription.Resource(0)) }, "") {}, "test_data", ) Loading @@ -143,7 +143,7 @@ class QSTileLoggerTest : SysuiTestCase() { fun testLogStateUpdate() { underTest.logStateUpdate( TileSpec.create("test_spec"), QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {}, QSTileState.build({ Icon.Resource(0, ContentDescription.Resource(0)) }, "") {}, "test_data", ) Loading Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt +13 −9 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -47,6 +46,8 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn Loading @@ -57,6 +58,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** * Provides a hassle-free way to implement new tiles according to current System UI architecture Loading @@ -83,10 +85,8 @@ class QSTileViewModelImpl<DATA_TYPE>( private val users: MutableStateFlow<UserHandle> = MutableStateFlow(userRepository.getSelectedUserInfo().userHandle) private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow() private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow() private val spec get() = config.tileSpec Loading Loading @@ -130,7 +130,7 @@ class QSTileViewModelImpl<DATA_TYPE>( tileData.replayCache.isNotEmpty(), state.replayCache.isNotEmpty() ) userInputs.tryEmit(userAction) tileScope.launch { userInputs.emit(userAction) } } override fun destroy() { Loading @@ -151,11 +151,16 @@ class QSTileViewModelImpl<DATA_TYPE>( emit(DataUpdateTrigger.InitialRequest) qsTileLogger.logInitialRequest(spec) } .shareIn(tileScope, SharingStarted.WhileSubscribed()) tileDataInteractor() .tileData(user, updateTriggers) // combine makes sure updateTriggers is always listened even if // tileDataInteractor#tileData doesn't flatMapLatest on it .combine(updateTriggers) { data, _ -> data } .cancellable() .flowOn(backgroundDispatcher) } .distinctUntilChanged() .shareIn( tileScope, SharingStarted.WhileSubscribed(), Loading @@ -171,8 +176,8 @@ class QSTileViewModelImpl<DATA_TYPE>( * * Subscribing to the result flow twice will result in doubling all actions, logs and analytics. */ private fun userInputFlow(user: UserHandle): Flow<DataUpdateTrigger> { return userInputs private fun userInputFlow(user: UserHandle): Flow<DataUpdateTrigger> = userInputs .filterFalseActions() .filterByPolicy(user) .throttle(CLICK_THROTTLE_DURATION, systemClock) Loading @@ -187,7 +192,6 @@ class QSTileViewModelImpl<DATA_TYPE>( } .onEach { userActionInteractor().handleInput(it.input) } .flowOn(backgroundDispatcher) } private fun Flow<QSTileUserAction>.filterByPolicy(user: UserHandle): Flow<QSTileUserAction> = config.policy.let { policy -> Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileConfig.kt +6 −6 Original line number Diff line number Diff line Loading @@ -36,9 +36,9 @@ data class QSTileConfig( */ sealed interface QSTileUIConfig { val tileIconRes: Int val iconRes: Int @DrawableRes get val tileLabelRes: Int val labelRes: Int @StringRes get /** Loading @@ -46,16 +46,16 @@ sealed interface QSTileUIConfig { * of [Resource]. Returns [Resources.ID_NULL] for each field. */ data object Empty : QSTileUIConfig { override val tileIconRes: Int override val iconRes: Int get() = Resources.ID_NULL override val tileLabelRes: Int override val labelRes: Int get() = Resources.ID_NULL } /** Config containing actual icon and label resources. */ data class Resource( @StringRes override val tileIconRes: Int, @StringRes override val tileLabelRes: Int, @DrawableRes override val iconRes: Int, @StringRes override val labelRes: Int, ) : QSTileUIConfig } Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt +12 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.qs.tiles.viewmodel import android.content.Context import android.service.quicksettings.Tile import com.android.systemui.common.shared.model.Icon Loading @@ -41,11 +42,19 @@ data class QSTileState( companion object { fun build( context: Context, config: QSTileUIConfig, build: Builder.() -> Unit ): QSTileState = build( { Icon.Resource(config.iconRes, null) }, context.getString(config.labelRes), build, ) fun build(icon: () -> Icon, label: CharSequence, build: Builder.() -> Unit): QSTileState = Builder(icon, label).apply(build).build() fun build(icon: Icon, label: CharSequence, build: Builder.() -> Unit): QSTileState = build({ icon }, label, build) } enum class ActivationState(val legacyState: Int) { Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt +1 −1 Original line number Diff line number Diff line Loading @@ -192,7 +192,7 @@ constructor( with(qsTileViewModel.config.uiConfig) { when (this) { is QSTileUIConfig.Empty -> qsTileViewModel.currentState?.label ?: "" is QSTileUIConfig.Resource -> context.getString(tileLabelRes) is QSTileUIConfig.Resource -> context.getString(labelRes) } } Loading
packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt +2 −2 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ class QSTileLoggerTest : SysuiTestCase() { underTest.logUserActionPipeline( TileSpec.create("test_spec"), QSTileUserAction.Click(null), QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {}, QSTileState.build({ Icon.Resource(0, ContentDescription.Resource(0)) }, "") {}, "test_data", ) Loading @@ -143,7 +143,7 @@ class QSTileLoggerTest : SysuiTestCase() { fun testLogStateUpdate() { underTest.logStateUpdate( TileSpec.create("test_spec"), QSTileState.build(Icon.Resource(0, ContentDescription.Resource(0)), "") {}, QSTileState.build({ Icon.Resource(0, ContentDescription.Resource(0)) }, "") {}, "test_data", ) Loading