[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:
Caitlin Shkuratov
2022-12-29 19:13:09 +00:00
parent a7790accf3
commit 6746a755bd
7 changed files with 422 additions and 32 deletions

View File

@@ -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,

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,
)