[SB Refactor] Implement demo mode for carrier merged wifi.
Bug: 238425913 Bug: 264684296 Test: `adb shell am broadcast -a com.android.systemui.demo -e command network -e wifi carriermerged -e level 2` -> displays a mobile triangle with level 2 and "W+" as its RAT type Test: See additional test steps in second bug Test: existing demo mode commands for wifi and mobile still work Test: atest DemoModeConnectionsRepositoryTest Change-Id: I9414c0b2566dcc2c49fe78ad352f0cc981ae6404
This commit is contained in:
@@ -39,7 +39,11 @@ 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.mobile.data.repository.prod.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -60,15 +64,19 @@ import kotlinx.coroutines.launch
|
||||
class DemoMobileConnectionsRepository
|
||||
@Inject
|
||||
constructor(
|
||||
private val dataSource: DemoModeMobileConnectionDataSource,
|
||||
private val mobileDataSource: DemoModeMobileConnectionDataSource,
|
||||
private val wifiDataSource: DemoModeWifiDataSource,
|
||||
@Application private val scope: CoroutineScope,
|
||||
context: Context,
|
||||
private val logFactory: TableLogBufferFactory,
|
||||
) : MobileConnectionsRepository {
|
||||
|
||||
private var demoCommandJob: Job? = null
|
||||
private var mobileDemoCommandJob: Job? = null
|
||||
private var wifiDemoCommandJob: Job? = null
|
||||
|
||||
private var connectionRepoCache = mutableMapOf<Int, DemoMobileConnectionRepository>()
|
||||
private var carrierMergedSubId: Int? = null
|
||||
|
||||
private var connectionRepoCache = mutableMapOf<Int, CacheContainer>()
|
||||
private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionModel>()
|
||||
val demoModeFinishedEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||
|
||||
@@ -144,52 +152,83 @@ constructor(
|
||||
override val defaultMobileNetworkConnectivity = MutableStateFlow(MobileConnectivityModel())
|
||||
|
||||
override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
|
||||
return connectionRepoCache[subId]
|
||||
?: createDemoMobileConnectionRepo(subId).also { connectionRepoCache[subId] = it }
|
||||
val current = connectionRepoCache[subId]?.repo
|
||||
if (current != null) {
|
||||
return current
|
||||
}
|
||||
|
||||
val new = createDemoMobileConnectionRepo(subId)
|
||||
connectionRepoCache[subId] = new
|
||||
return new.repo
|
||||
}
|
||||
|
||||
private fun createDemoMobileConnectionRepo(subId: Int): DemoMobileConnectionRepository {
|
||||
val tableLogBuffer = logFactory.getOrCreate("DemoMobileConnectionLog [$subId]", 100)
|
||||
private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
|
||||
val tableLogBuffer =
|
||||
logFactory.getOrCreate(
|
||||
"DemoMobileConnectionLog [$subId]",
|
||||
MOBILE_CONNECTION_BUFFER_SIZE,
|
||||
)
|
||||
|
||||
return DemoMobileConnectionRepository(
|
||||
subId,
|
||||
tableLogBuffer,
|
||||
)
|
||||
val repo =
|
||||
DemoMobileConnectionRepository(
|
||||
subId,
|
||||
tableLogBuffer,
|
||||
)
|
||||
return CacheContainer(repo, lastMobileState = null)
|
||||
}
|
||||
|
||||
override val globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
||||
|
||||
fun startProcessingCommands() {
|
||||
demoCommandJob =
|
||||
mobileDemoCommandJob =
|
||||
scope.launch {
|
||||
dataSource.mobileEvents.filterNotNull().collect { event -> processEvent(event) }
|
||||
mobileDataSource.mobileEvents.filterNotNull().collect { event ->
|
||||
processMobileEvent(event)
|
||||
}
|
||||
}
|
||||
wifiDemoCommandJob =
|
||||
scope.launch {
|
||||
wifiDataSource.wifiEvents.filterNotNull().collect { event ->
|
||||
processWifiEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stopProcessingCommands() {
|
||||
demoCommandJob?.cancel()
|
||||
mobileDemoCommandJob?.cancel()
|
||||
wifiDemoCommandJob?.cancel()
|
||||
_subscriptions.value = listOf()
|
||||
connectionRepoCache.clear()
|
||||
subscriptionInfoCache.clear()
|
||||
}
|
||||
|
||||
private fun processEvent(event: FakeNetworkEventModel) {
|
||||
private fun processMobileEvent(event: FakeNetworkEventModel) {
|
||||
when (event) {
|
||||
is Mobile -> {
|
||||
processEnabledMobileState(event)
|
||||
}
|
||||
is MobileDisabled -> {
|
||||
processDisabledMobileState(event)
|
||||
maybeRemoveSubscription(event.subId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processWifiEvent(event: FakeWifiEventModel) {
|
||||
when (event) {
|
||||
is FakeWifiEventModel.WifiDisabled -> disableCarrierMerged()
|
||||
is FakeWifiEventModel.Wifi -> disableCarrierMerged()
|
||||
is FakeWifiEventModel.CarrierMerged -> processCarrierMergedWifiState(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processEnabledMobileState(state: Mobile) {
|
||||
// get or create the connection repo, and set its values
|
||||
val subId = state.subId ?: DEFAULT_SUB_ID
|
||||
maybeCreateSubscription(subId)
|
||||
|
||||
val connection = getRepoForSubId(subId)
|
||||
connectionRepoCache[subId]?.lastMobileState = state
|
||||
|
||||
// This is always true here, because we split out disabled states at the data-source level
|
||||
connection.dataEnabled.value = true
|
||||
connection.networkName.value = NetworkNameModel.Derived(state.name)
|
||||
@@ -198,14 +237,36 @@ constructor(
|
||||
connection.connectionInfo.value = state.toMobileConnectionModel()
|
||||
}
|
||||
|
||||
private fun processDisabledMobileState(state: MobileDisabled) {
|
||||
private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
|
||||
// The new carrier merged connection is for a different sub ID, so disable carrier merged
|
||||
// for the current (now old) sub
|
||||
if (carrierMergedSubId != event.subscriptionId) {
|
||||
disableCarrierMerged()
|
||||
}
|
||||
|
||||
// get or create the connection repo, and set its values
|
||||
val subId = event.subscriptionId
|
||||
maybeCreateSubscription(subId)
|
||||
carrierMergedSubId = subId
|
||||
|
||||
val connection = getRepoForSubId(subId)
|
||||
// This is always true here, because we split out disabled states at the data-source level
|
||||
connection.dataEnabled.value = true
|
||||
connection.networkName.value = NetworkNameModel.Derived(CARRIER_MERGED_NAME)
|
||||
connection.numberOfLevels.value = event.numberOfLevels
|
||||
connection.cdmaRoaming.value = false
|
||||
connection.connectionInfo.value = event.toMobileConnectionModel()
|
||||
Log.e("CCS", "output connection info = ${connection.connectionInfo.value}")
|
||||
}
|
||||
|
||||
private fun maybeRemoveSubscription(subId: Int?) {
|
||||
if (_subscriptions.value.isEmpty()) {
|
||||
// Nothing to do here
|
||||
return
|
||||
}
|
||||
|
||||
val subId =
|
||||
state.subId
|
||||
val finalSubId =
|
||||
subId
|
||||
?: run {
|
||||
// For sake of usability, we can allow for no subId arg if there is only one
|
||||
// subscription
|
||||
@@ -223,7 +284,21 @@ constructor(
|
||||
_subscriptions.value[0].subscriptionId
|
||||
}
|
||||
|
||||
removeSubscription(subId)
|
||||
removeSubscription(finalSubId)
|
||||
}
|
||||
|
||||
private fun disableCarrierMerged() {
|
||||
val currentCarrierMergedSubId = carrierMergedSubId ?: return
|
||||
|
||||
// If this sub ID was previously not carrier merged, we should reset it to its previous
|
||||
// connection.
|
||||
val lastMobileState = connectionRepoCache[carrierMergedSubId]?.lastMobileState
|
||||
if (lastMobileState != null) {
|
||||
processEnabledMobileState(lastMobileState)
|
||||
} else {
|
||||
// Otherwise, just remove the subscription entirely
|
||||
removeSubscription(currentCarrierMergedSubId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeSubscription(subId: Int) {
|
||||
@@ -251,6 +326,10 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel {
|
||||
return createCarrierMergedConnectionModel(this.level)
|
||||
}
|
||||
|
||||
private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
|
||||
val key = mobileMappingsReverseLookup.value[this] ?: "dis"
|
||||
return DefaultNetworkType(key)
|
||||
@@ -260,9 +339,17 @@ constructor(
|
||||
private const val TAG = "DemoMobileConnectionsRepo"
|
||||
|
||||
private const val DEFAULT_SUB_ID = 1
|
||||
|
||||
private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
|
||||
}
|
||||
}
|
||||
|
||||
class CacheContainer(
|
||||
var repo: DemoMobileConnectionRepository,
|
||||
/** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */
|
||||
var lastMobileState: Mobile?,
|
||||
)
|
||||
|
||||
class DemoMobileConnectionRepository(
|
||||
override val subId: Int,
|
||||
override val tableLogBuffer: TableLogBuffer,
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -43,10 +44,10 @@ constructor(
|
||||
|
||||
private fun Bundle.toWifiEvent(): FakeWifiEventModel? {
|
||||
val wifi = getString("wifi") ?: return null
|
||||
return if (wifi == "show") {
|
||||
activeWifiEvent()
|
||||
} else {
|
||||
FakeWifiEventModel.WifiDisabled
|
||||
return when (wifi) {
|
||||
"show" -> activeWifiEvent()
|
||||
"carriermerged" -> carrierMergedWifiEvent()
|
||||
else -> FakeWifiEventModel.WifiDisabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +65,14 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun Bundle.carrierMergedWifiEvent(): FakeWifiEventModel.CarrierMerged {
|
||||
val subId = getString("slot")?.toInt() ?: DEFAULT_CARRIER_MERGED_SUB_ID
|
||||
val level = getString("level")?.toInt() ?: 0
|
||||
val numberOfLevels = getString("numlevels")?.toInt() ?: DEFAULT_NUM_LEVELS
|
||||
|
||||
return FakeWifiEventModel.CarrierMerged(subId, level, numberOfLevels)
|
||||
}
|
||||
|
||||
private fun String.toActivity(): Int =
|
||||
when (this) {
|
||||
"inout" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT
|
||||
@@ -71,4 +80,8 @@ constructor(
|
||||
"out" -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT
|
||||
else -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_CARRIER_MERGED_SUB_ID = 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ constructor(
|
||||
private fun processEvent(event: FakeWifiEventModel) =
|
||||
when (event) {
|
||||
is FakeWifiEventModel.Wifi -> processEnabledWifiState(event)
|
||||
is FakeWifiEventModel.CarrierMerged -> processCarrierMergedWifiState(event)
|
||||
is FakeWifiEventModel.WifiDisabled -> processDisabledWifiState()
|
||||
}
|
||||
|
||||
@@ -85,6 +86,14 @@ constructor(
|
||||
_wifiNetwork.value = event.toWifiNetworkModel()
|
||||
}
|
||||
|
||||
private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
|
||||
_isWifiEnabled.value = true
|
||||
_isWifiDefault.value = true
|
||||
// TODO(b/238425913): Support activity in demo mode.
|
||||
_wifiActivity.value = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
|
||||
_wifiNetwork.value = event.toCarrierMergedModel()
|
||||
}
|
||||
|
||||
private fun FakeWifiEventModel.Wifi.toWifiNetworkModel(): WifiNetworkModel =
|
||||
WifiNetworkModel.Active(
|
||||
networkId = DEMO_NET_ID,
|
||||
@@ -99,7 +108,13 @@ constructor(
|
||||
passpointProviderFriendlyName = null,
|
||||
)
|
||||
|
||||
// TODO(b/238425913): Add carrier merged support.
|
||||
private fun FakeWifiEventModel.CarrierMerged.toCarrierMergedModel(): WifiNetworkModel =
|
||||
WifiNetworkModel.CarrierMerged(
|
||||
networkId = DEMO_NET_ID,
|
||||
subscriptionId = subscriptionId,
|
||||
level = level,
|
||||
numberOfLevels = numberOfLevels,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val DEMO_NET_ID = 1234
|
||||
|
||||
@@ -29,5 +29,11 @@ sealed interface FakeWifiEventModel {
|
||||
val validated: Boolean?,
|
||||
) : FakeWifiEventModel
|
||||
|
||||
data class CarrierMerged(
|
||||
val subscriptionId: Int,
|
||||
val level: Int,
|
||||
val numberOfLevels: Int,
|
||||
) : FakeWifiEventModel
|
||||
|
||||
object WifiDisabled : FakeWifiEventModel
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.Mobil
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
||||
import com.android.systemui.util.mockito.mock
|
||||
@@ -72,7 +73,8 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
private lateinit var underTest: MobileRepositorySwitcher
|
||||
private lateinit var realRepo: MobileConnectionsRepositoryImpl
|
||||
private lateinit var demoRepo: DemoMobileConnectionsRepository
|
||||
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
|
||||
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
|
||||
private lateinit var wifiDataSource: DemoModeWifiDataSource
|
||||
private lateinit var logFactory: TableLogBufferFactory
|
||||
private lateinit var wifiRepository: FakeWifiRepository
|
||||
|
||||
@@ -98,10 +100,14 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
// Never start in demo mode
|
||||
whenever(demoModeController.isInDemoMode).thenReturn(false)
|
||||
|
||||
mockDataSource =
|
||||
mobileDataSource =
|
||||
mock<DemoModeMobileConnectionDataSource>().also {
|
||||
whenever(it.mobileEvents).thenReturn(fakeNetworkEventsFlow)
|
||||
}
|
||||
wifiDataSource =
|
||||
mock<DemoModeWifiDataSource>().also {
|
||||
whenever(it.wifiEvents).thenReturn(MutableStateFlow(null))
|
||||
}
|
||||
wifiRepository = FakeWifiRepository()
|
||||
|
||||
realRepo =
|
||||
@@ -122,7 +128,8 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
|
||||
demoRepo =
|
||||
DemoMobileConnectionsRepository(
|
||||
dataSource = mockDataSource,
|
||||
mobileDataSource = mobileDataSource,
|
||||
wifiDataSource = wifiDataSource,
|
||||
scope = scope,
|
||||
context = context,
|
||||
logFactory = logFactory,
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectio
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||
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.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
@@ -63,10 +65,12 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
private val testScope = TestScope(testDispatcher)
|
||||
|
||||
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
|
||||
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
|
||||
|
||||
private lateinit var connectionsRepo: DemoMobileConnectionsRepository
|
||||
private lateinit var underTest: DemoMobileConnectionRepository
|
||||
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
|
||||
private lateinit var mockWifiDataSource: DemoModeWifiDataSource
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@@ -75,10 +79,15 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
mock<DemoModeMobileConnectionDataSource>().also {
|
||||
whenever(it.mobileEvents).thenReturn(fakeNetworkEventFlow)
|
||||
}
|
||||
mockWifiDataSource =
|
||||
mock<DemoModeWifiDataSource>().also {
|
||||
whenever(it.wifiEvents).thenReturn(fakeWifiEventFlow)
|
||||
}
|
||||
|
||||
connectionsRepo =
|
||||
DemoMobileConnectionsRepository(
|
||||
dataSource = mockDataSource,
|
||||
mobileDataSource = mockDataSource,
|
||||
wifiDataSource = mockWifiDataSource,
|
||||
scope = testScope.backgroundScope,
|
||||
context = context,
|
||||
logFactory = logFactory,
|
||||
|
||||
@@ -32,6 +32,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionMod
|
||||
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.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
@@ -57,21 +59,28 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
private val testScope = TestScope(testDispatcher)
|
||||
|
||||
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
|
||||
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
|
||||
|
||||
private lateinit var underTest: DemoMobileConnectionsRepository
|
||||
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
|
||||
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
|
||||
private lateinit var wifiDataSource: DemoModeWifiDataSource
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
// The data source only provides one API, so we can mock it with a flow here for convenience
|
||||
mockDataSource =
|
||||
mobileDataSource =
|
||||
mock<DemoModeMobileConnectionDataSource>().also {
|
||||
whenever(it.mobileEvents).thenReturn(fakeNetworkEventFlow)
|
||||
}
|
||||
wifiDataSource =
|
||||
mock<DemoModeWifiDataSource>().also {
|
||||
whenever(it.wifiEvents).thenReturn(fakeWifiEventFlow)
|
||||
}
|
||||
|
||||
underTest =
|
||||
DemoMobileConnectionsRepository(
|
||||
dataSource = mockDataSource,
|
||||
mobileDataSource = mobileDataSource,
|
||||
wifiDataSource = wifiDataSource,
|
||||
scope = testScope.backgroundScope,
|
||||
context = context,
|
||||
logFactory = logFactory,
|
||||
@@ -96,6 +105,22 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `wifi carrier merged event - create new subscription`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
|
||||
|
||||
assertThat(latest).hasSize(1)
|
||||
assertThat(latest!![0].subscriptionId).isEqualTo(5)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network event - reuses subscription when same Id`() =
|
||||
testScope.runTest {
|
||||
@@ -118,6 +143,28 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `wifi carrier merged event - reuses subscription when same Id`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 1)
|
||||
|
||||
assertThat(latest).hasSize(1)
|
||||
assertThat(latest!![0].subscriptionId).isEqualTo(5)
|
||||
|
||||
// Second network event comes in with the same subId, does not create a new subscription
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 2)
|
||||
|
||||
assertThat(latest).hasSize(1)
|
||||
assertThat(latest!![0].subscriptionId).isEqualTo(5)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `multiple subscriptions`() =
|
||||
testScope.runTest {
|
||||
@@ -132,6 +179,35 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mobile subscription and carrier merged subscription`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
|
||||
|
||||
assertThat(latest).hasSize(2)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `multiple mobile subscriptions and carrier merged subscription`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 2)
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 3)
|
||||
|
||||
assertThat(latest).hasSize(3)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mobile disabled event - disables connection - subId specified - single conn`() =
|
||||
testScope.runTest {
|
||||
@@ -194,6 +270,112 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `wifi network updates to disabled - carrier merged connection removed`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
|
||||
|
||||
assertThat(latest).hasSize(1)
|
||||
|
||||
fakeWifiEventFlow.value = FakeWifiEventModel.WifiDisabled
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `wifi network updates to active - carrier merged connection removed`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
|
||||
|
||||
assertThat(latest).hasSize(1)
|
||||
|
||||
fakeWifiEventFlow.value =
|
||||
FakeWifiEventModel.Wifi(
|
||||
level = 1,
|
||||
activity = 0,
|
||||
ssid = null,
|
||||
validated = true,
|
||||
)
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mobile sub updates to carrier merged - only one connection`() =
|
||||
testScope.runTest {
|
||||
var latestSubsList: List<SubscriptionModel>? = null
|
||||
var connections: List<DemoMobileConnectionRepository>? = null
|
||||
val job =
|
||||
underTest.subscriptions
|
||||
.onEach { latestSubsList = it }
|
||||
.onEach { infos ->
|
||||
connections =
|
||||
infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
|
||||
}
|
||||
.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 3, level = 2)
|
||||
assertThat(latestSubsList).hasSize(1)
|
||||
|
||||
val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
|
||||
fakeWifiEventFlow.value = carrierMergedEvent
|
||||
assertThat(latestSubsList).hasSize(1)
|
||||
val connection = connections!!.find { it.subId == 3 }!!
|
||||
assertCarrierMergedConnection(connection, carrierMergedEvent)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `mobile sub updates to carrier merged then back - has old mobile data`() =
|
||||
testScope.runTest {
|
||||
var latestSubsList: List<SubscriptionModel>? = null
|
||||
var connections: List<DemoMobileConnectionRepository>? = null
|
||||
val job =
|
||||
underTest.subscriptions
|
||||
.onEach { latestSubsList = it }
|
||||
.onEach { infos ->
|
||||
connections =
|
||||
infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
|
||||
}
|
||||
.launchIn(this)
|
||||
|
||||
val mobileEvent = validMobileEvent(subId = 3, level = 2)
|
||||
fakeNetworkEventFlow.value = mobileEvent
|
||||
assertThat(latestSubsList).hasSize(1)
|
||||
|
||||
val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
|
||||
fakeWifiEventFlow.value = carrierMergedEvent
|
||||
assertThat(latestSubsList).hasSize(1)
|
||||
var connection = connections!!.find { it.subId == 3 }!!
|
||||
assertCarrierMergedConnection(connection, carrierMergedEvent)
|
||||
|
||||
// WHEN the carrier merged is removed
|
||||
fakeWifiEventFlow.value =
|
||||
FakeWifiEventModel.Wifi(
|
||||
level = 4,
|
||||
activity = 0,
|
||||
ssid = null,
|
||||
validated = true,
|
||||
)
|
||||
|
||||
// THEN the subId=3 connection goes back to the mobile information
|
||||
connection = connections!!.find { it.subId == 3 }!!
|
||||
assertConnection(connection, mobileEvent)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
/** Regression test for b/261706421 */
|
||||
@Test
|
||||
fun `multiple connections - remove all - does not throw`() =
|
||||
@@ -289,6 +471,51 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `demo connection - two connections - update carrier merged - no affect on first`() =
|
||||
testScope.runTest {
|
||||
var currentEvent1 = validMobileEvent(subId = 1)
|
||||
var connection1: DemoMobileConnectionRepository? = null
|
||||
var currentEvent2 = validCarrierMergedEvent(subId = 2)
|
||||
var connection2: DemoMobileConnectionRepository? = null
|
||||
var connections: List<DemoMobileConnectionRepository>? = null
|
||||
val job =
|
||||
underTest.subscriptions
|
||||
.onEach { infos ->
|
||||
connections =
|
||||
infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
|
||||
}
|
||||
.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = currentEvent1
|
||||
fakeWifiEventFlow.value = currentEvent2
|
||||
assertThat(connections).hasSize(2)
|
||||
connections!!.forEach {
|
||||
when (it.subId) {
|
||||
1 -> connection1 = it
|
||||
2 -> connection2 = it
|
||||
else -> Assert.fail("Unexpected subscription")
|
||||
}
|
||||
}
|
||||
|
||||
assertConnection(connection1!!, currentEvent1)
|
||||
assertCarrierMergedConnection(connection2!!, currentEvent2)
|
||||
|
||||
// WHEN the event changes for connection 2, it updates, and connection 1 stays the same
|
||||
currentEvent2 = validCarrierMergedEvent(subId = 2, level = 4)
|
||||
fakeWifiEventFlow.value = currentEvent2
|
||||
assertConnection(connection1!!, currentEvent1)
|
||||
assertCarrierMergedConnection(connection2!!, currentEvent2)
|
||||
|
||||
// and vice versa
|
||||
currentEvent1 = validMobileEvent(subId = 1, inflateStrength = true)
|
||||
fakeNetworkEventFlow.value = currentEvent1
|
||||
assertConnection(connection1!!, currentEvent1)
|
||||
assertCarrierMergedConnection(connection2!!, currentEvent2)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
private fun assertConnection(
|
||||
conn: DemoMobileConnectionRepository,
|
||||
model: FakeNetworkEventModel
|
||||
@@ -315,6 +542,21 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertCarrierMergedConnection(
|
||||
conn: DemoMobileConnectionRepository,
|
||||
model: FakeWifiEventModel.CarrierMerged,
|
||||
) {
|
||||
val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
|
||||
assertThat(conn.subId).isEqualTo(model.subscriptionId)
|
||||
assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false)
|
||||
assertThat(connectionInfo.isRoaming).isEqualTo(false)
|
||||
assertThat(connectionInfo.isEmergencyOnly).isFalse()
|
||||
assertThat(connectionInfo.isGsm).isFalse()
|
||||
assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected)
|
||||
}
|
||||
}
|
||||
|
||||
/** Convenience to create a valid fake network event with minimal params */
|
||||
@@ -339,3 +581,14 @@ fun validMobileEvent(
|
||||
roaming = roaming,
|
||||
name = "demo name",
|
||||
)
|
||||
|
||||
fun validCarrierMergedEvent(
|
||||
subId: Int = 1,
|
||||
level: Int = 1,
|
||||
numberOfLevels: Int = 4,
|
||||
): FakeWifiEventModel.CarrierMerged =
|
||||
FakeWifiEventModel.CarrierMerged(
|
||||
subscriptionId = subId,
|
||||
level = level,
|
||||
numberOfLevels = numberOfLevels,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user