[Sb refactor] show data activity in Mobile view

Adds support for reading the config `config_showActivity`, and uses the
new `DataActivityModel` type to show the data activity in the mobile
view model / view binder

Test: MobileIconViewModelTest
Test: MobileConnectionRepositoryTest
Test: DemoMobileConnectionParameterizedTest
Test: manual demo mode
Bug: 238425913
Change-Id: Id413d57d6c694ea6f324b022f6d215ae71b22074
This commit is contained in:
Evan Laird
2022-12-07 18:00:25 -05:00
parent d4c86b4e98
commit 0fb69e956b
15 changed files with 258 additions and 24 deletions

View File

@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.pipeline.mobile.data.model
import android.annotation.IntRange
import android.telephony.Annotation.DataActivityType
import android.telephony.CellSignalStrength
import android.telephony.TelephonyCallback.CarrierNetworkListener
import android.telephony.TelephonyCallback.DataActivityListener
@@ -28,6 +27,7 @@ import android.telephony.TelephonyCallback.SignalStrengthsListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
/**
* Data class containing all of the relevant information for a particular line of service, known as
@@ -54,7 +54,11 @@ data class MobileConnectionModel(
val dataConnectionState: DataConnectionState = Disconnected,
/** From [DataActivityListener.onDataActivity]. See [TelephonyManager] for the values */
@DataActivityType val dataActivityDirection: Int? = null,
val dataActivityDirection: DataActivityModel =
DataActivityModel(
hasActivityIn = false,
hasActivityOut = false,
),
/** From [CarrierNetworkListener.onCarrierNetworkChange] */
val carrierNetworkChangeActive: Boolean = false,

View File

@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
import android.content.Context
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
import android.util.Log
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileMappings
@@ -34,6 +35,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -236,7 +238,7 @@ constructor(
primaryLevel = level ?: 0,
dataConnectionState =
DataConnectionState.Connected, // TODO(b/261029387): not yet supported
dataActivityDirection = activity,
dataActivityDirection = (activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel(),
carrierNetworkChangeActive = carrierNetworkChange,
resolvedNetworkType = dataType.toResolvedNetworkType()
)

View File

@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -137,7 +138,10 @@ class MobileConnectionRepositoryImpl(
}
override fun onDataActivity(direction: Int) {
state = state.copy(dataActivityDirection = direction)
state =
state.copy(
dataActivityDirection = direction.toMobileDataActivityModel()
)
trySend(state)
}

View File

@@ -21,9 +21,11 @@ import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.util.CarrierConfigTracker
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -32,6 +34,9 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
interface MobileIconInteractor {
/** The current mobile data activity */
val activity: Flow<DataActivityModel>
/** Only true if mobile is the default transport but is not validated, otherwise false */
val isDefaultConnectionFailed: StateFlow<Boolean>
@@ -82,6 +87,8 @@ class MobileIconInteractorImpl(
) : MobileIconInteractor {
private val connectionInfo = connectionRepository.connectionInfo
override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled
override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.mobile.ui.binder
import android.content.res.ColorStateList
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.ViewGroup
@@ -40,6 +41,9 @@ object MobileIconBinder {
view: ViewGroup,
viewModel: MobileIconViewModel,
) {
val activityContainer = view.requireViewById<View>(R.id.inout_container)
val activityIn = view.requireViewById<ImageView>(R.id.mobile_in)
val activityOut = view.requireViewById<ImageView>(R.id.mobile_out)
val networkTypeView = view.requireViewById<ImageView>(R.id.mobile_type)
val iconView = view.requireViewById<ImageView>(R.id.mobile_signal)
val mobileDrawable = SignalDrawable(view.context).also { iconView.setImageDrawable(it) }
@@ -74,6 +78,15 @@ object MobileIconBinder {
}
}
// Set the activity indicators
launch { viewModel.activityInVisible.collect { activityIn.isVisible = it } }
launch { viewModel.activityOutVisible.collect { activityOut.isVisible = it } }
launch {
viewModel.activityContainerVisible.collect { activityContainer.isVisible = it }
}
// Set the tint
launch {
viewModel.tint.collect { tint ->
@@ -81,6 +94,8 @@ object MobileIconBinder {
iconView.imageTintList = tintList
networkTypeView.imageTintList = tintList
roamingView.imageTintList = tintList
activityIn.imageTintList = tintList
activityOut.imageTintList = tintList
}
}
}

View File

@@ -22,13 +22,16 @@ import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
/**
@@ -48,6 +51,7 @@ constructor(
val subscriptionId: Int,
iconInteractor: MobileIconInteractor,
logger: ConnectivityPipelineLogger,
constants: ConnectivityConstants,
) {
/** Whether or not to show the error state of [SignalDrawable] */
private val showExclamationMark: Flow<Boolean> =
@@ -89,5 +93,17 @@ constructor(
val roaming: Flow<Boolean> = iconInteractor.isRoaming
private val activity: Flow<DataActivityModel?> =
if (!constants.shouldShowActivityConfig) {
flowOf(null)
} else {
iconInteractor.activity
}
val activityInVisible: Flow<Boolean> = activity.map { it?.hasActivityIn ?: false }
val activityOutVisible: Flow<Boolean> = activity.map { it?.hasActivityOut ?: false }
val activityContainerVisible: Flow<Boolean> =
activity.map { it != null && (it.hasActivityIn || it.hasActivityOut) }
val tint: Flow<Int> = flowOf(Color.CYAN)
}

View File

@@ -20,6 +20,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import javax.inject.Inject
import kotlinx.coroutines.InternalCoroutinesApi
@@ -36,13 +37,15 @@ constructor(
val subscriptionIdsFlow: StateFlow<List<Int>>,
private val interactor: MobileIconsInteractor,
private val logger: ConnectivityPipelineLogger,
private val constants: ConnectivityConstants,
) {
/** TODO: do we need to cache these? */
fun viewModelForSub(subId: Int): MobileIconViewModel =
MobileIconViewModel(
subId,
interactor.createMobileConnectionInteractorForSubId(subId),
logger
logger,
constants,
)
class Factory
@@ -50,12 +53,14 @@ constructor(
constructor(
private val interactor: MobileIconsInteractor,
private val logger: ConnectivityPipelineLogger,
private val constants: ConnectivityConstants,
) {
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
return MobileIconsViewModel(
subscriptionIdsFlow,
interactor,
logger,
constants,
)
}
}

View File

@@ -16,8 +16,10 @@
package com.android.systemui.statusbar.pipeline.shared
import android.content.Context
import android.telephony.TelephonyManager
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
@@ -32,15 +34,25 @@ import javax.inject.Inject
@SysUISingleton
class ConnectivityConstants
@Inject
constructor(dumpManager: DumpManager, telephonyManager: TelephonyManager) : Dumpable {
constructor(
context: Context,
dumpManager: DumpManager,
telephonyManager: TelephonyManager,
) : Dumpable {
init {
dumpManager.registerDumpable("${SB_LOGGING_TAG}Constants", this)
dumpManager.registerNormalDumpable("${SB_LOGGING_TAG}Constants", this)
}
/** True if this device has the capability for data connections and false otherwise. */
val hasDataCapabilities = telephonyManager.isDataCapable
/** True if we should show the activityIn/activityOut icons and false otherwise */
val shouldShowActivityConfig = context.resources.getBoolean(R.bool.config_showActivity)
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.apply { println("hasDataCapabilities=$hasDataCapabilities") }
pw.apply {
println("hasDataCapabilities=$hasDataCapabilities")
println("shouldShowActivityConfig=$shouldShowActivityConfig")
}
}
}

View File

@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.pipeline.shared.data.model
import android.net.wifi.WifiManager
import android.telephony.Annotation
import android.telephony.TelephonyManager
import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger
@@ -44,3 +47,25 @@ data class DataActivityModel(
const val ACTIVITY_PREFIX = "dataActivity"
private const val COL_ACTIVITY_IN = "in"
private const val COL_ACTIVITY_OUT = "out"
fun @receiver:Annotation.DataActivityType Int.toMobileDataActivityModel(): DataActivityModel =
when (this) {
TelephonyManager.DATA_ACTIVITY_IN ->
DataActivityModel(hasActivityIn = true, hasActivityOut = false)
TelephonyManager.DATA_ACTIVITY_OUT ->
DataActivityModel(hasActivityIn = false, hasActivityOut = true)
TelephonyManager.DATA_ACTIVITY_INOUT ->
DataActivityModel(hasActivityIn = true, hasActivityOut = true)
else -> DataActivityModel(hasActivityIn = false, hasActivityOut = false)
}
fun Int.toWifiDataActivityModel(): DataActivityModel =
when (this) {
WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN ->
DataActivityModel(hasActivityIn = true, hasActivityOut = false)
WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT ->
DataActivityModel(hasActivityIn = false, hasActivityOut = true)
WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT ->
DataActivityModel(hasActivityIn = true, hasActivityOut = true)
else -> DataActivityModel(hasActivityIn = false, hasActivityOut = false)
}

View File

@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -237,7 +238,7 @@ class WifiRepositoryImpl @Inject constructor(
conflatedCallbackFlow {
val callback = TrafficStateCallback { state ->
logger.logInputChange("onTrafficStateChange", prettyPrintActivity(state))
trySend(trafficStateToDataActivityModel(state))
trySend(state.toWifiDataActivityModel())
}
wifiManager.registerTrafficStateCallback(mainExecutor, callback)
awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
@@ -266,15 +267,6 @@ class WifiRepositoryImpl @Inject constructor(
// NetworkCallback inside [wifiNetwork] for our wifi network information.
val WIFI_NETWORK_DEFAULT = WifiNetworkModel.Inactive
private fun trafficStateToDataActivityModel(state: Int): DataActivityModel {
return DataActivityModel(
hasActivityIn = state == TrafficStateCallback.DATA_ACTIVITY_IN ||
state == TrafficStateCallback.DATA_ACTIVITY_INOUT,
hasActivityOut = state == TrafficStateCallback.DATA_ACTIVITY_OUT ||
state == TrafficStateCallback.DATA_ACTIVITY_INOUT,
)
}
private fun networkCapabilitiesToWifiInfo(
networkCapabilities: NetworkCapabilities
): WifiInfo? {

View File

@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
import android.telephony.Annotation
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
import androidx.test.filters.SmallTest
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.TelephonyIcons
@@ -25,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -114,7 +116,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
assertThat(conn.subId).isEqualTo(model.subId)
assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
assertThat(connectionInfo.dataActivityDirection).isEqualTo(model.activity)
assertThat(connectionInfo.dataActivityDirection)
.isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
assertThat(connectionInfo.carrierNetworkChangeActive)
.isEqualTo(model.carrierNetworkChange)
assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
import androidx.test.filters.SmallTest
import com.android.settingslib.SignalIcon
@@ -27,6 +28,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectio
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -289,7 +291,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
assertThat(conn.subId).isEqualTo(model.subId)
assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
assertThat(connectionInfo.dataActivityDirection).isEqualTo(model.activity)
assertThat(connectionInfo.dataActivityDirection)
.isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
assertThat(connectionInfo.carrierNetworkChangeActive)
.isEqualTo(model.carrierNetworkChange)
assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)

View File

@@ -23,10 +23,16 @@ import android.telephony.ServiceState
import android.telephony.SignalStrength
import android.telephony.SubscriptionInfo
import android.telephony.TelephonyCallback
import android.telephony.TelephonyCallback.DataActivityListener
import android.telephony.TelephonyCallback.ServiceStateListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.DATA_ACTIVITY_DORMANT
import android.telephony.TelephonyManager.DATA_ACTIVITY_IN
import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
import android.telephony.TelephonyManager.DATA_ACTIVITY_OUT
import android.telephony.TelephonyManager.DATA_CONNECTED
import android.telephony.TelephonyManager.DATA_CONNECTING
import android.telephony.TelephonyManager.DATA_DISCONNECTED
@@ -46,6 +52,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetwork
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
@@ -249,10 +257,11 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
var latest: MobileConnectionModel? = null
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
val callback = getTelephonyCallbackForType<TelephonyCallback.DataActivityListener>()
callback.onDataActivity(3)
val callback = getTelephonyCallbackForType<DataActivityListener>()
callback.onDataActivity(DATA_ACTIVITY_INOUT)
assertThat(latest?.dataActivityDirection).isEqualTo(3)
assertThat(latest?.dataActivityDirection)
.isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
job.cancel()
}
@@ -459,6 +468,44 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
job.cancel()
}
@Test
fun `activity - updates from callback`() =
runBlocking(IMMEDIATE) {
var latest: DataActivityModel? = null
val job =
underTest.connectionInfo.onEach { latest = it.dataActivityDirection }.launchIn(this)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
val cb = getTelephonyCallbackForType<DataActivityListener>()
cb.onDataActivity(DATA_ACTIVITY_IN)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
cb.onDataActivity(DATA_ACTIVITY_OUT)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
cb.onDataActivity(DATA_ACTIVITY_INOUT)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
cb.onDataActivity(DATA_ACTIVITY_NONE)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
cb.onDataActivity(DATA_ACTIVITY_DORMANT)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
cb.onDataActivity(1234)
assertThat(latest)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
job.cancel()
}
private fun getTelephonyCallbacks(): List<TelephonyCallback> {
val callbackCaptor = argumentCaptor<TelephonyCallback>()
Mockito.verify(telephonyManager).registerTelephonyCallback(any(), callbackCaptor.capture())

View File

@@ -19,11 +19,20 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
import android.telephony.CellSignalStrength
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import kotlinx.coroutines.flow.MutableStateFlow
class FakeMobileIconInteractor : MobileIconInteractor {
override val alwaysShowDataRatIcon = MutableStateFlow(false)
override val activity =
MutableStateFlow(
DataActivityModel(
hasActivityIn = false,
hasActivityOut = false,
)
)
private val _iconGroup = MutableStateFlow<SignalIcon.MobileIconGroup>(TelephonyIcons.THREE_G)
override val networkTypeIconGroup = _iconGroup

View File

@@ -23,7 +23,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
@@ -40,6 +43,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
private lateinit var underTest: MobileIconViewModel
private val interactor = FakeMobileIconInteractor()
@Mock private lateinit var logger: ConnectivityPipelineLogger
@Mock private lateinit var constants: ConnectivityConstants
@Before
fun setUp() {
@@ -53,7 +57,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
setNumberOfLevels(4)
isDataConnected.value = true
}
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger)
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
}
@Test
@@ -250,6 +254,92 @@ class MobileIconViewModelTest : SysuiTestCase() {
job.cancel()
}
@Test
fun `data activity - null when config is off`() =
runBlocking(IMMEDIATE) {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(false)
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
var inVisible: Boolean? = null
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
var outVisible: Boolean? = null
val outJob = underTest.activityInVisible.onEach { outVisible = it }.launchIn(this)
var containerVisible: Boolean? = null
val containerJob =
underTest.activityInVisible.onEach { containerVisible = it }.launchIn(this)
interactor.activity.value =
DataActivityModel(
hasActivityIn = true,
hasActivityOut = true,
)
assertThat(inVisible).isFalse()
assertThat(outVisible).isFalse()
assertThat(containerVisible).isFalse()
inJob.cancel()
outJob.cancel()
containerJob.cancel()
}
@Test
fun `data activity - config on - test indicators`() =
runBlocking(IMMEDIATE) {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(true)
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
var inVisible: Boolean? = null
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
var outVisible: Boolean? = null
val outJob = underTest.activityOutVisible.onEach { outVisible = it }.launchIn(this)
var containerVisible: Boolean? = null
val containerJob =
underTest.activityContainerVisible.onEach { containerVisible = it }.launchIn(this)
interactor.activity.value =
DataActivityModel(
hasActivityIn = true,
hasActivityOut = false,
)
yield()
assertThat(inVisible).isTrue()
assertThat(outVisible).isFalse()
assertThat(containerVisible).isTrue()
interactor.activity.value =
DataActivityModel(
hasActivityIn = false,
hasActivityOut = true,
)
assertThat(inVisible).isFalse()
assertThat(outVisible).isTrue()
assertThat(containerVisible).isTrue()
interactor.activity.value =
DataActivityModel(
hasActivityIn = false,
hasActivityOut = false,
)
assertThat(inVisible).isFalse()
assertThat(outVisible).isFalse()
assertThat(containerVisible).isFalse()
inJob.cancel()
outJob.cancel()
containerJob.cancel()
}
/** Convenience constructor for these tests */
private fun defaultSignal(
level: Int = 1,