1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
18 
19 import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
20 import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
21 import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
22 import androidx.test.ext.junit.runners.AndroidJUnit4
23 import androidx.test.filters.SmallTest
24 import com.android.settingslib.SignalIcon
25 import com.android.settingslib.mobile.TelephonyIcons.THREE_G
26 import com.android.systemui.SysuiTestCase
27 import com.android.systemui.log.table.tableLogBufferFactory
28 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
29 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
30 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
31 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
32 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
33 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
34 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
35 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
36 import com.android.systemui.testKosmos
37 import com.android.systemui.util.mockito.mock
38 import com.android.systemui.util.mockito.whenever
39 import com.google.common.truth.Truth.assertThat
40 import junit.framework.Assert
41 import kotlinx.coroutines.ExperimentalCoroutinesApi
42 import kotlinx.coroutines.Job
43 import kotlinx.coroutines.flow.MutableStateFlow
44 import kotlinx.coroutines.flow.launchIn
45 import kotlinx.coroutines.flow.onEach
46 import kotlinx.coroutines.launch
47 import kotlinx.coroutines.test.TestScope
48 import kotlinx.coroutines.test.UnconfinedTestDispatcher
49 import kotlinx.coroutines.test.runTest
50 import org.junit.Before
51 import org.junit.Test
52 import org.junit.runner.RunWith
53 
54 @OptIn(ExperimentalCoroutinesApi::class)
55 @SmallTest
56 @RunWith(AndroidJUnit4::class)
57 class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
58     private val kosmos = testKosmos()
59 
60     private val testDispatcher = UnconfinedTestDispatcher()
61     private val testScope = TestScope(testDispatcher)
62 
63     private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
64     private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
65 
66     private lateinit var underTest: DemoMobileConnectionsRepository
67     private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
68     private lateinit var wifiDataSource: DemoModeWifiDataSource
69 
70     @Before
71     fun setUp() {
72         // The data source only provides one API, so we can mock it with a flow here for convenience
73         mobileDataSource =
74             mock<DemoModeMobileConnectionDataSource>().also {
75                 whenever(it.mobileEvents).thenReturn(fakeNetworkEventFlow)
76             }
77         wifiDataSource =
78             mock<DemoModeWifiDataSource>().also {
79                 whenever(it.wifiEvents).thenReturn(fakeWifiEventFlow)
80             }
81 
82         underTest =
83             DemoMobileConnectionsRepository(
84                 mobileDataSource = mobileDataSource,
85                 wifiDataSource = wifiDataSource,
86                 scope = testScope.backgroundScope,
87                 context = context,
88                 logFactory = kosmos.tableLogBufferFactory,
89             )
90 
91         underTest.startProcessingCommands()
92     }
93 
94     @Test
95     fun isDefault_defaultsToTrue() =
96         testScope.runTest {
97             val isDefault = underTest.mobileIsDefault.value
98             assertThat(isDefault).isTrue()
99         }
100 
101     @Test
102     fun validated_defaultsToTrue() =
103         testScope.runTest {
104             val isValidated = underTest.defaultConnectionIsValidated.value
105             assertThat(isValidated).isTrue()
106         }
107 
108     @Test
109     fun networkEvent_createNewSubscription() =
110         testScope.runTest {
111             var latest: List<SubscriptionModel>? = null
112             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
113 
114             assertThat(latest).isEmpty()
115 
116             fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
117 
118             assertThat(latest).hasSize(1)
119             assertThat(latest!![0].subscriptionId).isEqualTo(1)
120 
121             job.cancel()
122         }
123 
124     @Test
125     fun wifiCarrierMergedEvent_createNewSubscription() =
126         testScope.runTest {
127             var latest: List<SubscriptionModel>? = null
128             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
129 
130             assertThat(latest).isEmpty()
131 
132             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
133 
134             assertThat(latest).hasSize(1)
135             assertThat(latest!![0].subscriptionId).isEqualTo(5)
136 
137             job.cancel()
138         }
139 
140     @Test
141     fun networkEvent_reusesSubscriptionWhenSameId() =
142         testScope.runTest {
143             var latest: List<SubscriptionModel>? = null
144             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
145 
146             assertThat(latest).isEmpty()
147 
148             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
149 
150             assertThat(latest).hasSize(1)
151             assertThat(latest!![0].subscriptionId).isEqualTo(1)
152 
153             // Second network event comes in with the same subId, does not create a new subscription
154             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 2)
155 
156             assertThat(latest).hasSize(1)
157             assertThat(latest!![0].subscriptionId).isEqualTo(1)
158 
159             job.cancel()
160         }
161 
162     @Test
163     fun wifiCarrierMergedEvent_reusesSubscriptionWhenSameId() =
164         testScope.runTest {
165             var latest: List<SubscriptionModel>? = null
166             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
167 
168             assertThat(latest).isEmpty()
169 
170             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 1)
171 
172             assertThat(latest).hasSize(1)
173             assertThat(latest!![0].subscriptionId).isEqualTo(5)
174 
175             // Second network event comes in with the same subId, does not create a new subscription
176             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5, level = 2)
177 
178             assertThat(latest).hasSize(1)
179             assertThat(latest!![0].subscriptionId).isEqualTo(5)
180 
181             job.cancel()
182         }
183 
184     @Test
185     fun multipleSubscriptions() =
186         testScope.runTest {
187             var latest: List<SubscriptionModel>? = null
188             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
189 
190             fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
191             fakeNetworkEventFlow.value = validMobileEvent(subId = 2)
192 
193             assertThat(latest).hasSize(2)
194 
195             job.cancel()
196         }
197 
198     @Test
199     fun mobileSubscriptionAndCarrierMergedSubscription() =
200         testScope.runTest {
201             var latest: List<SubscriptionModel>? = null
202             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
203 
204             fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
205             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 5)
206 
207             assertThat(latest).hasSize(2)
208 
209             job.cancel()
210         }
211 
212     @Test
213     fun multipleMobileSubscriptionsAndCarrierMergedSubscription() =
214         testScope.runTest {
215             var latest: List<SubscriptionModel>? = null
216             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
217 
218             fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
219             fakeNetworkEventFlow.value = validMobileEvent(subId = 2)
220             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 3)
221 
222             assertThat(latest).hasSize(3)
223 
224             job.cancel()
225         }
226 
227     @Test
228     fun mobileDisabledEvent_disablesConnection_subIdSpecified_singleConn() =
229         testScope.runTest {
230             var latest: List<SubscriptionModel>? = null
231             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
232 
233             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
234 
235             fakeNetworkEventFlow.value = MobileDisabled(subId = 1)
236 
237             assertThat(latest).hasSize(0)
238 
239             job.cancel()
240         }
241 
242     @Test
243     fun mobileDisabledEvent_disablesConnection_subIdNotSpecified_singleConn() =
244         testScope.runTest {
245             var latest: List<SubscriptionModel>? = null
246             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
247 
248             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
249 
250             fakeNetworkEventFlow.value = MobileDisabled(subId = null)
251 
252             assertThat(latest).hasSize(0)
253 
254             job.cancel()
255         }
256 
257     @Test
258     fun mobileDisabledEvent_disablesConnection_subIdSpecified_multipleConn() =
259         testScope.runTest {
260             var latest: List<SubscriptionModel>? = null
261             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
262 
263             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
264             fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
265 
266             fakeNetworkEventFlow.value = MobileDisabled(subId = 2)
267 
268             assertThat(latest).hasSize(1)
269 
270             job.cancel()
271         }
272 
273     @Test
274     fun mobileDisabledEvent_subIdNotSpecified_multipleConn_ignoresCommand() =
275         testScope.runTest {
276             var latest: List<SubscriptionModel>? = null
277             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
278 
279             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
280             fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
281 
282             fakeNetworkEventFlow.value = MobileDisabled(subId = null)
283 
284             assertThat(latest).hasSize(2)
285 
286             job.cancel()
287         }
288 
289     @Test
290     fun wifiNetworkUpdatesToDisabled_carrierMergedConnectionRemoved() =
291         testScope.runTest {
292             var latest: List<SubscriptionModel>? = null
293             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
294 
295             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
296 
297             assertThat(latest).hasSize(1)
298 
299             fakeWifiEventFlow.value = FakeWifiEventModel.WifiDisabled
300 
301             assertThat(latest).isEmpty()
302 
303             job.cancel()
304         }
305 
306     @Test
307     fun wifiNetworkUpdatesToActive_carrierMergedConnectionRemoved() =
308         testScope.runTest {
309             var latest: List<SubscriptionModel>? = null
310             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
311 
312             fakeWifiEventFlow.value = validCarrierMergedEvent(subId = 1)
313 
314             assertThat(latest).hasSize(1)
315 
316             fakeWifiEventFlow.value =
317                 FakeWifiEventModel.Wifi(
318                     level = 1,
319                     activity = 0,
320                     ssid = null,
321                     validated = true,
322                 )
323 
324             assertThat(latest).isEmpty()
325 
326             job.cancel()
327         }
328 
329     @Test
330     fun mobileSubUpdatesToCarrierMerged_onlyOneConnection() =
331         testScope.runTest {
332             var latestSubsList: List<SubscriptionModel>? = null
333             var connections: List<DemoMobileConnectionRepository>? = null
334             val job =
335                 underTest.subscriptions
336                     .onEach { latestSubsList = it }
337                     .onEach { infos ->
338                         connections =
339                             infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
340                     }
341                     .launchIn(this)
342 
343             fakeNetworkEventFlow.value = validMobileEvent(subId = 3, level = 2)
344             assertThat(latestSubsList).hasSize(1)
345 
346             val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
347             fakeWifiEventFlow.value = carrierMergedEvent
348             assertThat(latestSubsList).hasSize(1)
349             val connection = connections!!.find { it.subId == 3 }!!
350             assertCarrierMergedConnection(connection, carrierMergedEvent)
351 
352             job.cancel()
353         }
354 
355     @Test
356     fun mobileSubUpdatesToCarrierMergedThenBack_hasOldMobileData() =
357         testScope.runTest {
358             var latestSubsList: List<SubscriptionModel>? = null
359             var connections: List<DemoMobileConnectionRepository>? = null
360             val job =
361                 underTest.subscriptions
362                     .onEach { latestSubsList = it }
363                     .onEach { infos ->
364                         connections =
365                             infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
366                     }
367                     .launchIn(this)
368 
369             val mobileEvent = validMobileEvent(subId = 3, level = 2)
370             fakeNetworkEventFlow.value = mobileEvent
371             assertThat(latestSubsList).hasSize(1)
372 
373             val carrierMergedEvent = validCarrierMergedEvent(subId = 3, level = 1)
374             fakeWifiEventFlow.value = carrierMergedEvent
375             assertThat(latestSubsList).hasSize(1)
376             var connection = connections!!.find { it.subId == 3 }!!
377             assertCarrierMergedConnection(connection, carrierMergedEvent)
378 
379             // WHEN the carrier merged is removed
380             fakeWifiEventFlow.value =
381                 FakeWifiEventModel.Wifi(
382                     level = 4,
383                     activity = 0,
384                     ssid = null,
385                     validated = true,
386                 )
387 
388             // THEN the subId=3 connection goes back to the mobile information
389             connection = connections!!.find { it.subId == 3 }!!
390             assertConnection(connection, mobileEvent)
391 
392             job.cancel()
393         }
394 
395     /** Regression test for b/261706421 */
396     @Test
397     fun multipleConnections_removeAll_doesNotThrow() =
398         testScope.runTest {
399             var latest: List<SubscriptionModel>? = null
400             val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
401 
402             // Two subscriptions are added
403             fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
404             fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
405 
406             // Then both are removed by turning off demo mode
407             underTest.stopProcessingCommands()
408 
409             assertThat(latest).isEmpty()
410 
411             job.cancel()
412         }
413 
414     @Test
415     fun demoConnection_singleSubscription() =
416         testScope.runTest {
417             var currentEvent: FakeNetworkEventModel = validMobileEvent(subId = 1)
418             var connections: List<DemoMobileConnectionRepository>? = null
419             val job =
420                 underTest.subscriptions
421                     .onEach { infos ->
422                         connections =
423                             infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
424                     }
425                     .launchIn(this)
426 
427             fakeNetworkEventFlow.value = currentEvent
428 
429             assertThat(connections).hasSize(1)
430             val connection1 = connections!![0]
431 
432             assertConnection(connection1, currentEvent)
433 
434             // Exercise the whole api
435 
436             currentEvent = validMobileEvent(subId = 1, level = 2)
437             fakeNetworkEventFlow.value = currentEvent
438             assertConnection(connection1, currentEvent)
439 
440             job.cancel()
441         }
442 
443     @Test
444     fun demoConnection_twoConnections_updateSecond_noAffectOnFirst() =
445         testScope.runTest {
446             var currentEvent1 = validMobileEvent(subId = 1)
447             var connection1: DemoMobileConnectionRepository? = null
448             var currentEvent2 = validMobileEvent(subId = 2)
449             var connection2: DemoMobileConnectionRepository? = null
450             var connections: List<DemoMobileConnectionRepository>? = null
451             val job =
452                 underTest.subscriptions
453                     .onEach { infos ->
454                         connections =
455                             infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
456                     }
457                     .launchIn(this)
458 
459             fakeNetworkEventFlow.value = currentEvent1
460             fakeNetworkEventFlow.value = currentEvent2
461             assertThat(connections).hasSize(2)
462             connections!!.forEach {
463                 if (it.subId == 1) {
464                     connection1 = it
465                 } else if (it.subId == 2) {
466                     connection2 = it
467                 } else {
468                     Assert.fail("Unexpected subscription")
469                 }
470             }
471 
472             assertConnection(connection1!!, currentEvent1)
473             assertConnection(connection2!!, currentEvent2)
474 
475             // WHEN the event changes for connection 2, it updates, and connection 1 stays the same
476             currentEvent2 = validMobileEvent(subId = 2, activity = DATA_ACTIVITY_INOUT)
477             fakeNetworkEventFlow.value = currentEvent2
478             assertConnection(connection1!!, currentEvent1)
479             assertConnection(connection2!!, currentEvent2)
480 
481             // and vice versa
482             currentEvent1 = validMobileEvent(subId = 1, inflateStrength = true)
483             fakeNetworkEventFlow.value = currentEvent1
484             assertConnection(connection1!!, currentEvent1)
485             assertConnection(connection2!!, currentEvent2)
486 
487             job.cancel()
488         }
489 
490     @Test
491     fun demoConnection_twoConnections_updateCarrierMerged_noAffectOnFirst() =
492         testScope.runTest {
493             var currentEvent1 = validMobileEvent(subId = 1)
494             var connection1: DemoMobileConnectionRepository? = null
495             var currentEvent2 = validCarrierMergedEvent(subId = 2)
496             var connection2: DemoMobileConnectionRepository? = null
497             var connections: List<DemoMobileConnectionRepository>? = null
498             val job =
499                 underTest.subscriptions
500                     .onEach { infos ->
501                         connections =
502                             infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
503                     }
504                     .launchIn(this)
505 
506             fakeNetworkEventFlow.value = currentEvent1
507             fakeWifiEventFlow.value = currentEvent2
508             assertThat(connections).hasSize(2)
509             connections!!.forEach {
510                 when (it.subId) {
511                     1 -> connection1 = it
512                     2 -> connection2 = it
513                     else -> Assert.fail("Unexpected subscription")
514                 }
515             }
516 
517             assertConnection(connection1!!, currentEvent1)
518             assertCarrierMergedConnection(connection2!!, currentEvent2)
519 
520             // WHEN the event changes for connection 2, it updates, and connection 1 stays the same
521             currentEvent2 = validCarrierMergedEvent(subId = 2, level = 4)
522             fakeWifiEventFlow.value = currentEvent2
523             assertConnection(connection1!!, currentEvent1)
524             assertCarrierMergedConnection(connection2!!, currentEvent2)
525 
526             // and vice versa
527             currentEvent1 = validMobileEvent(subId = 1, inflateStrength = true)
528             fakeNetworkEventFlow.value = currentEvent1
529             assertConnection(connection1!!, currentEvent1)
530             assertCarrierMergedConnection(connection2!!, currentEvent2)
531 
532             job.cancel()
533         }
534 
535     @Test
536     fun demoIsNotInEcmState() = testScope.runTest { assertThat(underTest.isInEcmMode()).isFalse() }
537 
538     private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
539         val job = launch {
540             launch { conn.cdmaLevel.collect {} }
541             launch { conn.primaryLevel.collect {} }
542             launch { conn.dataActivityDirection.collect {} }
543             launch { conn.carrierNetworkChangeActive.collect {} }
544             launch { conn.isRoaming.collect {} }
545             launch { conn.networkName.collect {} }
546             launch { conn.carrierName.collect {} }
547             launch { conn.isEmergencyOnly.collect {} }
548             launch { conn.dataConnectionState.collect {} }
549             launch { conn.hasPrioritizedNetworkCapabilities.collect {} }
550         }
551         return job
552     }
553 
554     private fun TestScope.assertConnection(
555         conn: DemoMobileConnectionRepository,
556         model: FakeNetworkEventModel,
557     ) {
558         val job = startCollection(conn)
559         // Assert the fields using the `MutableStateFlow` so that we don't have to start up
560         // a collector for every field for every test
561         when (model) {
562             is FakeNetworkEventModel.Mobile -> {
563                 assertThat(conn.subId).isEqualTo(model.subId)
564                 assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
565                 assertThat(conn.primaryLevel.value).isEqualTo(model.level)
566                 assertThat(conn.dataActivityDirection.value)
567                     .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
568                 assertThat(conn.carrierNetworkChangeActive.value)
569                     .isEqualTo(model.carrierNetworkChange)
570                 assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
571                 assertThat(conn.networkName.value)
572                     .isEqualTo(NetworkNameModel.IntentDerived(model.name))
573                 assertThat(conn.carrierName.value)
574                     .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}"))
575                 assertThat(conn.hasPrioritizedNetworkCapabilities.value).isEqualTo(model.slice)
576                 assertThat(conn.isNonTerrestrial.value).isEqualTo(model.ntn)
577 
578                 // TODO(b/261029387) check these once we start handling them
579                 assertThat(conn.isEmergencyOnly.value).isFalse()
580                 assertThat(conn.isGsm.value).isFalse()
581                 assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
582             }
583             else -> {}
584         }
585 
586         job.cancel()
587     }
588 
589     private fun TestScope.assertCarrierMergedConnection(
590         conn: DemoMobileConnectionRepository,
591         model: FakeWifiEventModel.CarrierMerged,
592     ) {
593         val job = startCollection(conn)
594         assertThat(conn.subId).isEqualTo(model.subscriptionId)
595         assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
596         assertThat(conn.primaryLevel.value).isEqualTo(model.level)
597         assertThat(conn.carrierNetworkChangeActive.value).isEqualTo(false)
598         assertThat(conn.isRoaming.value).isEqualTo(false)
599         assertThat(conn.isEmergencyOnly.value).isFalse()
600         assertThat(conn.isGsm.value).isFalse()
601         assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
602         assertThat(conn.hasPrioritizedNetworkCapabilities.value).isFalse()
603         job.cancel()
604     }
605 }
606 
607 /** Convenience to create a valid fake network event with minimal params */
validMobileEventnull608 fun validMobileEvent(
609     level: Int? = 1,
610     dataType: SignalIcon.MobileIconGroup? = THREE_G,
611     subId: Int? = 1,
612     carrierId: Int? = UNKNOWN_CARRIER_ID,
613     inflateStrength: Boolean = false,
614     activity: Int? = null,
615     carrierNetworkChange: Boolean = false,
616     roaming: Boolean = false,
617 ): FakeNetworkEventModel =
618     FakeNetworkEventModel.Mobile(
619         level = level,
620         dataType = dataType,
621         subId = subId,
622         carrierId = carrierId,
623         inflateStrength = inflateStrength,
624         activity = activity,
625         carrierNetworkChange = carrierNetworkChange,
626         roaming = roaming,
627         name = "demo name",
628     )
629 
630 fun validCarrierMergedEvent(
631     subId: Int = 1,
632     level: Int = 1,
633     numberOfLevels: Int = 4,
634     activity: Int = DATA_ACTIVITY_NONE,
635 ): FakeWifiEventModel.CarrierMerged =
636     FakeWifiEventModel.CarrierMerged(
637         subscriptionId = subId,
638         level = level,
639         numberOfLevels = numberOfLevels,
640         activity = activity,
641     )
642