1 /*
2  * 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.prod
18 
19 import android.content.BroadcastReceiver
20 import android.content.Context
21 import android.content.Intent
22 import android.net.ConnectivityManager
23 import android.net.ConnectivityManager.NetworkCallback
24 import android.platform.test.annotations.DisableFlags
25 import android.platform.test.annotations.EnableFlags
26 import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN
27 import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN
28 import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL
29 import android.telephony.CarrierConfigManager.KEY_SHOW_5G_SLICE_ICON_BOOL
30 import android.telephony.NetworkRegistrationInfo
31 import android.telephony.NetworkRegistrationInfo.DOMAIN_PS
32 import android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_DENIED
33 import android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME
34 import android.telephony.ServiceState
35 import android.telephony.ServiceState.STATE_IN_SERVICE
36 import android.telephony.ServiceState.STATE_OUT_OF_SERVICE
37 import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX
38 import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
39 import android.telephony.TelephonyCallback
40 import android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener
41 import android.telephony.TelephonyCallback.DataActivityListener
42 import android.telephony.TelephonyCallback.DisplayInfoListener
43 import android.telephony.TelephonyCallback.ServiceStateListener
44 import android.telephony.TelephonyDisplayInfo
45 import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA
46 import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
47 import android.telephony.TelephonyManager
48 import android.telephony.TelephonyManager.DATA_ACTIVITY_DORMANT
49 import android.telephony.TelephonyManager.DATA_ACTIVITY_IN
50 import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
51 import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
52 import android.telephony.TelephonyManager.DATA_ACTIVITY_OUT
53 import android.telephony.TelephonyManager.DATA_CONNECTED
54 import android.telephony.TelephonyManager.DATA_CONNECTING
55 import android.telephony.TelephonyManager.DATA_DISCONNECTED
56 import android.telephony.TelephonyManager.DATA_DISCONNECTING
57 import android.telephony.TelephonyManager.DATA_HANDOVER_IN_PROGRESS
58 import android.telephony.TelephonyManager.DATA_SUSPENDED
59 import android.telephony.TelephonyManager.DATA_UNKNOWN
60 import android.telephony.TelephonyManager.ERI_OFF
61 import android.telephony.TelephonyManager.ERI_ON
62 import android.telephony.TelephonyManager.EXTRA_CARRIER_ID
63 import android.telephony.TelephonyManager.EXTRA_DATA_SPN
64 import android.telephony.TelephonyManager.EXTRA_PLMN
65 import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
66 import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
67 import android.telephony.TelephonyManager.EXTRA_SPN
68 import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
69 import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
70 import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
71 import androidx.test.ext.junit.runners.AndroidJUnit4
72 import androidx.test.filters.SmallTest
73 import com.android.settingslib.mobile.MobileMappings
74 import com.android.systemui.Flags
75 import com.android.systemui.SysuiTestCase
76 import com.android.systemui.coroutines.collectLastValue
77 import com.android.systemui.flags.FakeFeatureFlagsClassic
78 import com.android.systemui.flags.Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO
79 import com.android.systemui.log.table.TableLogBuffer
80 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
81 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
82 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
83 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
84 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
85 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
86 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
87 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
88 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
89 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride
90 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
91 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
92 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
93 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.telephonyDisplayInfo
94 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
95 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
96 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
97 import com.android.systemui.util.mockito.mock
98 import com.android.systemui.util.mockito.whenever
99 import com.android.systemui.util.mockito.withArgCaptor
100 import com.google.common.truth.Truth.assertThat
101 import kotlinx.coroutines.ExperimentalCoroutinesApi
102 import kotlinx.coroutines.flow.MutableStateFlow
103 import kotlinx.coroutines.flow.launchIn
104 import kotlinx.coroutines.flow.onEach
105 import kotlinx.coroutines.test.TestScope
106 import kotlinx.coroutines.test.UnconfinedTestDispatcher
107 import kotlinx.coroutines.test.runTest
108 import org.junit.Before
109 import org.junit.Test
110 import org.junit.runner.RunWith
111 import org.mockito.Mock
112 import org.mockito.Mockito.verify
113 import org.mockito.MockitoAnnotations
114 import org.mockito.kotlin.any
115 import org.mockito.kotlin.argumentCaptor
116 
117 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
118 @OptIn(ExperimentalCoroutinesApi::class)
119 @SmallTest
120 @RunWith(AndroidJUnit4::class)
121 class MobileConnectionRepositoryTest : SysuiTestCase() {
122     private lateinit var underTest: MobileConnectionRepositoryImpl
123 
124     private val flags =
<lambda>null125         FakeFeatureFlagsClassic().also { it.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
126 
127     @Mock private lateinit var connectivityManager: ConnectivityManager
128     @Mock private lateinit var telephonyManager: TelephonyManager
129     @Mock private lateinit var logger: MobileInputLogger
130     @Mock private lateinit var tableLogger: TableLogBuffer
131     @Mock private lateinit var context: Context
132 
133     private val mobileMappings = FakeMobileMappingsProxy()
134     private val systemUiCarrierConfig =
135         SystemUiCarrierConfig(
136             SUB_1_ID,
137             createTestConfig(),
138         )
139 
140     private val testDispatcher = UnconfinedTestDispatcher()
141     private val testScope = TestScope(testDispatcher)
142 
143     private val subscriptionModel: MutableStateFlow<SubscriptionModel?> =
144         MutableStateFlow(
145             SubscriptionModel(
146                 subscriptionId = SUB_1_ID,
147                 carrierName = DEFAULT_NAME,
148                 profileClass = PROFILE_CLASS_UNSET,
149             )
150         )
151 
152     @Before
setUpnull153     fun setUp() {
154         MockitoAnnotations.initMocks(this)
155         whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
156 
157         underTest =
158             MobileConnectionRepositoryImpl(
159                 SUB_1_ID,
160                 context,
161                 subscriptionModel,
162                 DEFAULT_NAME_MODEL,
163                 SEP,
164                 connectivityManager,
165                 telephonyManager,
166                 systemUiCarrierConfig,
167                 fakeBroadcastDispatcher,
168                 mobileMappings,
169                 testDispatcher,
170                 logger,
171                 tableLogger,
172                 flags,
173                 testScope.backgroundScope,
174             )
175     }
176 
177     @Test
emergencyOnlynull178     fun emergencyOnly() =
179         testScope.runTest {
180             var latest: Boolean? = null
181             val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
182 
183             val serviceState = ServiceState()
184             serviceState.isEmergencyOnly = true
185 
186             getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
187 
188             assertThat(latest).isEqualTo(true)
189 
190             job.cancel()
191         }
192 
193     @Test
emergencyOnly_togglesnull194     fun emergencyOnly_toggles() =
195         testScope.runTest {
196             var latest: Boolean? = null
197             val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
198 
199             val callback = getTelephonyCallbackForType<ServiceStateListener>()
200             callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = true })
201             assertThat(latest).isTrue()
202 
203             callback.onServiceStateChanged(ServiceState().also { it.isEmergencyOnly = false })
204 
205             assertThat(latest).isFalse()
206 
207             job.cancel()
208         }
209 
210     @Test
cdmaLevelUpdatesnull211     fun cdmaLevelUpdates() =
212         testScope.runTest {
213             var latest: Int? = null
214             val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
215 
216             val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
217             var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
218             callback.onSignalStrengthsChanged(strength)
219 
220             assertThat(latest).isEqualTo(2)
221 
222             // gsmLevel updates, no change to cdmaLevel
223             strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
224             callback.onSignalStrengthsChanged(strength)
225 
226             assertThat(latest).isEqualTo(2)
227 
228             job.cancel()
229         }
230 
231     @Test
gsmLevelUpdatesnull232     fun gsmLevelUpdates() =
233         testScope.runTest {
234             var latest: Int? = null
235             val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
236 
237             val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
238             var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
239             callback.onSignalStrengthsChanged(strength)
240 
241             assertThat(latest).isEqualTo(1)
242 
243             strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
244             callback.onSignalStrengthsChanged(strength)
245 
246             assertThat(latest).isEqualTo(3)
247 
248             job.cancel()
249         }
250 
251     @Test
isGsmnull252     fun isGsm() =
253         testScope.runTest {
254             var latest: Boolean? = null
255             val job = underTest.isGsm.onEach { latest = it }.launchIn(this)
256 
257             val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
258             var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
259             callback.onSignalStrengthsChanged(strength)
260 
261             assertThat(latest).isTrue()
262 
263             strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = false)
264             callback.onSignalStrengthsChanged(strength)
265 
266             assertThat(latest).isFalse()
267 
268             job.cancel()
269         }
270 
271     @Test
dataConnectionState_connectednull272     fun dataConnectionState_connected() =
273         testScope.runTest {
274             var latest: DataConnectionState? = null
275             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
276 
277             val callback =
278                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
279             callback.onDataConnectionStateChanged(DATA_CONNECTED, 200 /* unused */)
280 
281             assertThat(latest).isEqualTo(DataConnectionState.Connected)
282 
283             job.cancel()
284         }
285 
286     @Test
dataConnectionState_connectingnull287     fun dataConnectionState_connecting() =
288         testScope.runTest {
289             var latest: DataConnectionState? = null
290             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
291 
292             val callback =
293                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
294             callback.onDataConnectionStateChanged(DATA_CONNECTING, 200 /* unused */)
295 
296             assertThat(latest).isEqualTo(DataConnectionState.Connecting)
297 
298             job.cancel()
299         }
300 
301     @Test
dataConnectionState_disconnectednull302     fun dataConnectionState_disconnected() =
303         testScope.runTest {
304             var latest: DataConnectionState? = null
305             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
306 
307             val callback =
308                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
309             callback.onDataConnectionStateChanged(DATA_DISCONNECTED, 200 /* unused */)
310 
311             assertThat(latest).isEqualTo(DataConnectionState.Disconnected)
312 
313             job.cancel()
314         }
315 
316     @Test
dataConnectionState_disconnectingnull317     fun dataConnectionState_disconnecting() =
318         testScope.runTest {
319             var latest: DataConnectionState? = null
320             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
321 
322             val callback =
323                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
324             callback.onDataConnectionStateChanged(DATA_DISCONNECTING, 200 /* unused */)
325 
326             assertThat(latest).isEqualTo(DataConnectionState.Disconnecting)
327 
328             job.cancel()
329         }
330 
331     @Test
dataConnectionState_suspendednull332     fun dataConnectionState_suspended() =
333         testScope.runTest {
334             var latest: DataConnectionState? = null
335             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
336 
337             val callback =
338                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
339             callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */)
340 
341             assertThat(latest).isEqualTo(DataConnectionState.Suspended)
342 
343             job.cancel()
344         }
345 
346     @Test
dataConnectionState_handoverInProgressnull347     fun dataConnectionState_handoverInProgress() =
348         testScope.runTest {
349             var latest: DataConnectionState? = null
350             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
351 
352             val callback =
353                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
354             callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */)
355 
356             assertThat(latest).isEqualTo(DataConnectionState.HandoverInProgress)
357 
358             job.cancel()
359         }
360 
361     @Test
dataConnectionState_unknownnull362     fun dataConnectionState_unknown() =
363         testScope.runTest {
364             var latest: DataConnectionState? = null
365             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
366 
367             val callback =
368                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
369             callback.onDataConnectionStateChanged(DATA_UNKNOWN, 200 /* unused */)
370 
371             assertThat(latest).isEqualTo(DataConnectionState.Unknown)
372 
373             job.cancel()
374         }
375 
376     @Test
dataConnectionState_invalidnull377     fun dataConnectionState_invalid() =
378         testScope.runTest {
379             var latest: DataConnectionState? = null
380             val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
381 
382             val callback =
383                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
384             callback.onDataConnectionStateChanged(45, 200 /* unused */)
385 
386             assertThat(latest).isEqualTo(DataConnectionState.Invalid)
387 
388             job.cancel()
389         }
390 
391     @Test
dataActivitynull392     fun dataActivity() =
393         testScope.runTest {
394             var latest: DataActivityModel? = null
395             val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
396 
397             val callback = getTelephonyCallbackForType<DataActivityListener>()
398             callback.onDataActivity(DATA_ACTIVITY_INOUT)
399 
400             assertThat(latest).isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
401 
402             job.cancel()
403         }
404 
405     @Test
carrierId_initialValueCapturednull406     fun carrierId_initialValueCaptured() =
407         testScope.runTest {
408             whenever(telephonyManager.simCarrierId).thenReturn(1234)
409 
410             var latest: Int? = null
411             val job = underTest.carrierId.onEach { latest = it }.launchIn(this)
412 
413             assertThat(latest).isEqualTo(1234)
414 
415             job.cancel()
416         }
417 
418     @Test
carrierId_updatesOnBroadcastnull419     fun carrierId_updatesOnBroadcast() =
420         testScope.runTest {
421             whenever(telephonyManager.simCarrierId).thenReturn(1234)
422 
423             var latest: Int? = null
424             val job = underTest.carrierId.onEach { latest = it }.launchIn(this)
425 
426             fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
427                 context,
428                 carrierIdIntent(carrierId = 4321),
429             )
430 
431             assertThat(latest).isEqualTo(4321)
432 
433             job.cancel()
434         }
435 
436     @Test
carrierNetworkChangenull437     fun carrierNetworkChange() =
438         testScope.runTest {
439             var latest: Boolean? = null
440             val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
441 
442             val callback = getTelephonyCallbackForType<TelephonyCallback.CarrierNetworkListener>()
443             callback.onCarrierNetworkChange(true)
444 
445             assertThat(latest).isEqualTo(true)
446 
447             job.cancel()
448         }
449 
450     @Test
networkType_defaultnull451     fun networkType_default() =
452         testScope.runTest {
453             var latest: ResolvedNetworkType? = null
454             val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
455 
456             val expected = UnknownNetworkType
457 
458             assertThat(latest).isEqualTo(expected)
459 
460             job.cancel()
461         }
462 
463     @Test
networkType_unknown_hasCorrectKeynull464     fun networkType_unknown_hasCorrectKey() =
465         testScope.runTest {
466             var latest: ResolvedNetworkType? = null
467             val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
468 
469             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
470             val ti =
471                 telephonyDisplayInfo(
472                     networkType = NETWORK_TYPE_UNKNOWN,
473                     overrideNetworkType = NETWORK_TYPE_UNKNOWN,
474                 )
475 
476             callback.onDisplayInfoChanged(ti)
477 
478             val expected = UnknownNetworkType
479             assertThat(latest).isEqualTo(expected)
480             assertThat(latest!!.lookupKey).isEqualTo(MobileMappings.toIconKey(NETWORK_TYPE_UNKNOWN))
481 
482             job.cancel()
483         }
484 
485     @Test
networkType_updatesUsingDefaultnull486     fun networkType_updatesUsingDefault() =
487         testScope.runTest {
488             var latest: ResolvedNetworkType? = null
489             val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
490 
491             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
492             val overrideType = OVERRIDE_NETWORK_TYPE_NONE
493             val type = NETWORK_TYPE_LTE
494             val ti = telephonyDisplayInfo(networkType = type, overrideNetworkType = overrideType)
495             callback.onDisplayInfoChanged(ti)
496 
497             val expected = DefaultNetworkType(mobileMappings.toIconKey(type))
498             assertThat(latest).isEqualTo(expected)
499 
500             job.cancel()
501         }
502 
503     @Test
networkType_updatesUsingOverridenull504     fun networkType_updatesUsingOverride() =
505         testScope.runTest {
506             var latest: ResolvedNetworkType? = null
507             val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
508 
509             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
510             val type = OVERRIDE_NETWORK_TYPE_LTE_CA
511             val ti = telephonyDisplayInfo(networkType = type, overrideNetworkType = type)
512             callback.onDisplayInfoChanged(ti)
513 
514             val expected = OverrideNetworkType(mobileMappings.toIconKeyOverride(type))
515             assertThat(latest).isEqualTo(expected)
516 
517             job.cancel()
518         }
519 
520     @Test
networkType_unknownNetworkWithOverride_usesOverrideKeynull521     fun networkType_unknownNetworkWithOverride_usesOverrideKey() =
522         testScope.runTest {
523             var latest: ResolvedNetworkType? = null
524             val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
525 
526             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
527             val unknown = NETWORK_TYPE_UNKNOWN
528             val type = OVERRIDE_NETWORK_TYPE_LTE_CA
529             val ti = telephonyDisplayInfo(unknown, type)
530             callback.onDisplayInfoChanged(ti)
531 
532             val expected = OverrideNetworkType(mobileMappings.toIconKeyOverride(type))
533             assertThat(latest).isEqualTo(expected)
534 
535             job.cancel()
536         }
537 
538     @Test
dataEnabled_initial_falsenull539     fun dataEnabled_initial_false() =
540         testScope.runTest {
541             whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
542 
543             assertThat(underTest.dataEnabled.value).isFalse()
544         }
545 
546     @Test
isDataEnabled_tracksTelephonyCallbacknull547     fun isDataEnabled_tracksTelephonyCallback() =
548         testScope.runTest {
549             var latest: Boolean? = null
550             val job = underTest.dataEnabled.onEach { latest = it }.launchIn(this)
551 
552             whenever(telephonyManager.isDataConnectionAllowed).thenReturn(false)
553             assertThat(underTest.dataEnabled.value).isFalse()
554 
555             val callback = getTelephonyCallbackForType<TelephonyCallback.DataEnabledListener>()
556 
557             callback.onDataEnabledChanged(true, 1)
558             assertThat(latest).isTrue()
559 
560             callback.onDataEnabledChanged(false, 1)
561             assertThat(latest).isFalse()
562 
563             job.cancel()
564         }
565 
566     @Test
numberOfLevels_isDefaultnull567     fun numberOfLevels_isDefault() =
568         testScope.runTest {
569             var latest: Int? = null
570             val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
571 
572             assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS)
573 
574             job.cancel()
575         }
576 
577     @Test
roaming_cdma_queriesTelephonyManagernull578     fun roaming_cdma_queriesTelephonyManager() =
579         testScope.runTest {
580             var latest: Boolean? = null
581             val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
582 
583             val cb = getTelephonyCallbackForType<ServiceStateListener>()
584 
585             // CDMA roaming is off, GSM roaming is on
586             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
587             cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
588 
589             assertThat(latest).isFalse()
590 
591             // CDMA roaming is on, GSM roaming is off
592             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_ON)
593             cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
594 
595             assertThat(latest).isTrue()
596 
597             job.cancel()
598         }
599 
600     /**
601      * [TelephonyManager.getCdmaEnhancedRoamingIndicatorDisplayNumber] returns -1 if the service is
602      * not running or if there is an error while retrieving the cdma ERI
603      */
604     @Test
cdmaRoaming_ignoresNegativeOnenull605     fun cdmaRoaming_ignoresNegativeOne() =
606         testScope.runTest {
607             var latest: Boolean? = null
608             val job = underTest.cdmaRoaming.onEach { latest = it }.launchIn(this)
609 
610             val serviceState = ServiceState()
611             serviceState.roaming = false
612 
613             val cb = getTelephonyCallbackForType<ServiceStateListener>()
614 
615             // CDMA roaming is unavailable (-1), GSM roaming is off
616             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(-1)
617             cb.onServiceStateChanged(serviceState)
618 
619             assertThat(latest).isFalse()
620 
621             job.cancel()
622         }
623 
624     @Test
roaming_gsm_queriesDisplayInfo_viaDisplayInfonull625     fun roaming_gsm_queriesDisplayInfo_viaDisplayInfo() =
626         testScope.runTest {
627             // GIVEN flag is true
628             flags.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true)
629 
630             // Re-create the repository, because the flag is read at init
631             underTest =
632                 MobileConnectionRepositoryImpl(
633                     SUB_1_ID,
634                     context,
635                     subscriptionModel,
636                     DEFAULT_NAME_MODEL,
637                     SEP,
638                     connectivityManager,
639                     telephonyManager,
640                     systemUiCarrierConfig,
641                     fakeBroadcastDispatcher,
642                     mobileMappings,
643                     testDispatcher,
644                     logger,
645                     tableLogger,
646                     flags,
647                     testScope.backgroundScope,
648                 )
649 
650             var latest: Boolean? = null
651             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
652 
653             val cb = getTelephonyCallbackForType<DisplayInfoListener>()
654 
655             // CDMA roaming is off, GSM roaming is off
656             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
657             cb.onDisplayInfoChanged(
658                 TelephonyDisplayInfo(NETWORK_TYPE_LTE, NETWORK_TYPE_UNKNOWN, false, false, false)
659             )
660 
661             assertThat(latest).isFalse()
662 
663             // CDMA roaming is off, GSM roaming is on
664             cb.onDisplayInfoChanged(
665                 TelephonyDisplayInfo(NETWORK_TYPE_LTE, NETWORK_TYPE_UNKNOWN, true, false, false)
666             )
667 
668             assertThat(latest).isTrue()
669 
670             job.cancel()
671         }
672 
673     @Test
roaming_gsm_queriesDisplayInfo_viaServiceStatenull674     fun roaming_gsm_queriesDisplayInfo_viaServiceState() =
675         testScope.runTest {
676             // GIVEN flag is false
677             flags.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, false)
678 
679             // Re-create the repository, because the flag is read at init
680             underTest =
681                 MobileConnectionRepositoryImpl(
682                     SUB_1_ID,
683                     context,
684                     subscriptionModel,
685                     DEFAULT_NAME_MODEL,
686                     SEP,
687                     connectivityManager,
688                     telephonyManager,
689                     systemUiCarrierConfig,
690                     fakeBroadcastDispatcher,
691                     mobileMappings,
692                     testDispatcher,
693                     logger,
694                     tableLogger,
695                     flags,
696                     testScope.backgroundScope,
697                 )
698 
699             var latest: Boolean? = null
700             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
701 
702             val cb = getTelephonyCallbackForType<ServiceStateListener>()
703 
704             // CDMA roaming is off, GSM roaming is off
705             whenever(telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber).thenReturn(ERI_OFF)
706             cb.onServiceStateChanged(ServiceState().also { it.roaming = false })
707 
708             assertThat(latest).isFalse()
709 
710             // CDMA roaming is off, GSM roaming is on
711             cb.onServiceStateChanged(ServiceState().also { it.roaming = true })
712 
713             assertThat(latest).isTrue()
714 
715             job.cancel()
716         }
717 
718     @Test
activity_updatesFromCallbacknull719     fun activity_updatesFromCallback() =
720         testScope.runTest {
721             var latest: DataActivityModel? = null
722             val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
723 
724             assertThat(latest)
725                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
726 
727             val cb = getTelephonyCallbackForType<DataActivityListener>()
728             cb.onDataActivity(DATA_ACTIVITY_IN)
729             assertThat(latest)
730                 .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = false))
731 
732             cb.onDataActivity(DATA_ACTIVITY_OUT)
733             assertThat(latest)
734                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = true))
735 
736             cb.onDataActivity(DATA_ACTIVITY_INOUT)
737             assertThat(latest)
738                 .isEqualTo(DataActivityModel(hasActivityIn = true, hasActivityOut = true))
739 
740             cb.onDataActivity(DATA_ACTIVITY_NONE)
741             assertThat(latest)
742                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
743 
744             cb.onDataActivity(DATA_ACTIVITY_DORMANT)
745             assertThat(latest)
746                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
747 
748             cb.onDataActivity(1234)
749             assertThat(latest)
750                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
751 
752             job.cancel()
753         }
754 
755     @Test
networkNameForSubId_updatesnull756     fun networkNameForSubId_updates() =
757         testScope.runTest {
758             var latest: NetworkNameModel? = null
759             val job = underTest.carrierName.onEach { latest = it }.launchIn(this)
760 
761             subscriptionModel.value =
762                 SubscriptionModel(
763                     subscriptionId = SUB_1_ID,
764                     carrierName = DEFAULT_NAME,
765                     profileClass = PROFILE_CLASS_UNSET,
766                 )
767 
768             assertThat(latest?.name).isEqualTo(DEFAULT_NAME)
769 
770             val updatedName = "Derived Carrier"
771             subscriptionModel.value =
772                 SubscriptionModel(
773                     subscriptionId = SUB_1_ID,
774                     carrierName = updatedName,
775                     profileClass = PROFILE_CLASS_UNSET,
776                 )
777 
778             assertThat(latest?.name).isEqualTo(updatedName)
779 
780             job.cancel()
781         }
782 
783     @Test
networkNameForSubId_defaultWhenSubscriptionModelNullnull784     fun networkNameForSubId_defaultWhenSubscriptionModelNull() =
785         testScope.runTest {
786             var latest: NetworkNameModel? = null
787             val job = underTest.carrierName.onEach { latest = it }.launchIn(this)
788 
789             subscriptionModel.value = null
790 
791             assertThat(latest?.name).isEqualTo(DEFAULT_NAME)
792 
793             job.cancel()
794         }
795 
796     @Test
networkName_defaultnull797     fun networkName_default() =
798         testScope.runTest {
799             var latest: NetworkNameModel? = null
800             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
801 
802             assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
803 
804             job.cancel()
805         }
806 
807     @Test
808     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_usesBroadcastInfo_returnsDerivednull809     fun networkName_usesBroadcastInfo_returnsDerived() =
810         testScope.runTest {
811             var latest: NetworkNameModel? = null
812             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
813 
814             val intent = spnIntent()
815             val captor = argumentCaptor<BroadcastReceiver>()
816             verify(context).registerReceiver(captor.capture(), any())
817             captor.lastValue.onReceive(context, intent)
818 
819             // spnIntent() sets all values to true and test strings
820             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
821 
822             job.cancel()
823         }
824 
825     @Test
826     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_usesBroadcastInfo_returnsDerived_flagOffnull827     fun networkName_usesBroadcastInfo_returnsDerived_flagOff() =
828         testScope.runTest {
829             var latest: NetworkNameModel? = null
830             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
831 
832             val intent = spnIntent()
833             val captor = argumentCaptor<BroadcastReceiver>()
834             verify(context).registerReceiver(captor.capture(), any())
835             captor.lastValue.onReceive(context, intent)
836 
837             // spnIntent() sets all values to true and test strings
838             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
839 
840             job.cancel()
841         }
842 
843     @Test
844     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_broadcastNotForThisSubId_keepsOldValuenull845     fun networkName_broadcastNotForThisSubId_keepsOldValue() =
846         testScope.runTest {
847             var latest: NetworkNameModel? = null
848             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
849 
850             val intent = spnIntent()
851             val captor = argumentCaptor<BroadcastReceiver>()
852             verify(context).registerReceiver(captor.capture(), any())
853             captor.lastValue.onReceive(context, intent)
854 
855             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
856 
857             // WHEN an intent with a different subId is sent
858             val wrongSubIntent = spnIntent(subId = 101)
859 
860             captor.lastValue.onReceive(context, wrongSubIntent)
861 
862             // THEN the previous intent's name is still used
863             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
864 
865             job.cancel()
866         }
867 
868     @Test
869     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_broadcastNotForThisSubId_keepsOldValue_flagOffnull870     fun networkName_broadcastNotForThisSubId_keepsOldValue_flagOff() =
871         testScope.runTest {
872             var latest: NetworkNameModel? = null
873             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
874 
875             val intent = spnIntent()
876             val captor = argumentCaptor<BroadcastReceiver>()
877             verify(context).registerReceiver(captor.capture(), any())
878             captor.lastValue.onReceive(context, intent)
879 
880             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
881 
882             // WHEN an intent with a different subId is sent
883             val wrongSubIntent = spnIntent(subId = 101)
884 
885             captor.lastValue.onReceive(context, wrongSubIntent)
886 
887             // THEN the previous intent's name is still used
888             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
889 
890             job.cancel()
891         }
892 
893     @Test
894     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_broadcastHasNoData_updatesToDefaultnull895     fun networkName_broadcastHasNoData_updatesToDefault() =
896         testScope.runTest {
897             var latest: NetworkNameModel? = null
898             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
899 
900             val intent = spnIntent()
901             val captor = argumentCaptor<BroadcastReceiver>()
902             verify(context).registerReceiver(captor.capture(), any())
903             captor.lastValue.onReceive(context, intent)
904 
905             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
906 
907             val intentWithoutInfo =
908                 spnIntent(
909                     showSpn = false,
910                     showPlmn = false,
911                 )
912 
913             captor.lastValue.onReceive(context, intentWithoutInfo)
914 
915             assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
916 
917             job.cancel()
918         }
919 
920     @Test
921     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_broadcastHasNoData_updatesToDefault_flagOffnull922     fun networkName_broadcastHasNoData_updatesToDefault_flagOff() =
923         testScope.runTest {
924             var latest: NetworkNameModel? = null
925             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
926 
927             val intent = spnIntent()
928             val captor = argumentCaptor<BroadcastReceiver>()
929             verify(context).registerReceiver(captor.capture(), any())
930             captor.lastValue.onReceive(context, intent)
931 
932             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
933 
934             val intentWithoutInfo =
935                 spnIntent(
936                     showSpn = false,
937                     showPlmn = false,
938                 )
939 
940             captor.lastValue.onReceive(context, intentWithoutInfo)
941 
942             assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
943 
944             job.cancel()
945         }
946 
947     @Test
948     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_usingEagerStrategy_retainsNameBetweenSubscribersnull949     fun networkName_usingEagerStrategy_retainsNameBetweenSubscribers() =
950         testScope.runTest {
951             // Use the [StateFlow.value] getter so we can prove that the collection happens
952             // even when there is no [Job]
953 
954             // Starts out default
955             assertThat(underTest.networkName.value).isEqualTo(DEFAULT_NAME_MODEL)
956 
957             val intent = spnIntent()
958             val captor = argumentCaptor<BroadcastReceiver>()
959             verify(context).registerReceiver(captor.capture(), any())
960             captor.lastValue.onReceive(context, intent)
961 
962             // The value is still there despite no active subscribers
963             assertThat(underTest.networkName.value)
964                 .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
965         }
966 
967     @Test
968     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_usingEagerStrategy_retainsNameBetweenSubscribers_flagOffnull969     fun networkName_usingEagerStrategy_retainsNameBetweenSubscribers_flagOff() =
970         testScope.runTest {
971             // Use the [StateFlow.value] getter so we can prove that the collection happens
972             // even when there is no [Job]
973 
974             // Starts out default
975             assertThat(underTest.networkName.value).isEqualTo(DEFAULT_NAME_MODEL)
976 
977             val intent = spnIntent()
978             val captor = argumentCaptor<BroadcastReceiver>()
979             verify(context).registerReceiver(captor.capture(), any())
980             captor.lastValue.onReceive(context, intent)
981 
982             // The value is still there despite no active subscribers
983             assertThat(underTest.networkName.value)
984                 .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
985         }
986 
987     @Test
988     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_allFieldsSet_prioritizesDataSpnOverSpnnull989     fun networkName_allFieldsSet_prioritizesDataSpnOverSpn() =
990         testScope.runTest {
991             val latest by collectLastValue(underTest.networkName)
992             val captor = argumentCaptor<BroadcastReceiver>()
993             verify(context).registerReceiver(captor.capture(), any())
994 
995             val intent =
996                 spnIntent(
997                     subId = SUB_1_ID,
998                     showSpn = true,
999                     spn = SPN,
1000                     dataSpn = DATA_SPN,
1001                     showPlmn = true,
1002                     plmn = PLMN,
1003                 )
1004             captor.lastValue.onReceive(context, intent)
1005             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
1006         }
1007 
1008     @Test
1009     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_spnAndPlmn_fallbackToSpnWhenNullDataSpnnull1010     fun networkName_spnAndPlmn_fallbackToSpnWhenNullDataSpn() =
1011         testScope.runTest {
1012             val latest by collectLastValue(underTest.networkName)
1013             val captor = argumentCaptor<BroadcastReceiver>()
1014             verify(context).registerReceiver(captor.capture(), any())
1015 
1016             val intent =
1017                 spnIntent(
1018                     subId = SUB_1_ID,
1019                     showSpn = true,
1020                     spn = SPN,
1021                     dataSpn = null,
1022                     showPlmn = true,
1023                     plmn = PLMN,
1024                 )
1025             captor.lastValue.onReceive(context, intent)
1026             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
1027         }
1028 
1029     @Test
1030     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_allFieldsSet_flagOffnull1031     fun networkName_allFieldsSet_flagOff() =
1032         testScope.runTest {
1033             val latest by collectLastValue(underTest.networkName)
1034             val captor = argumentCaptor<BroadcastReceiver>()
1035             verify(context).registerReceiver(captor.capture(), any())
1036 
1037             val intent =
1038                 spnIntent(
1039                     subId = SUB_1_ID,
1040                     showSpn = true,
1041                     spn = SPN,
1042                     dataSpn = DATA_SPN,
1043                     showPlmn = true,
1044                     plmn = PLMN,
1045                 )
1046             captor.lastValue.onReceive(context, intent)
1047             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
1048         }
1049 
1050     @Test
1051     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNotNull_showSpn_spnNull_dataSpnNotNullnull1052     fun networkName_showPlmn_plmnNotNull_showSpn_spnNull_dataSpnNotNull() =
1053         testScope.runTest {
1054             val latest by collectLastValue(underTest.networkName)
1055             val captor = argumentCaptor<BroadcastReceiver>()
1056             verify(context).registerReceiver(captor.capture(), any())
1057             val intent =
1058                 spnIntent(
1059                     subId = SUB_1_ID,
1060                     showSpn = true,
1061                     spn = null,
1062                     dataSpn = DATA_SPN,
1063                     showPlmn = true,
1064                     plmn = PLMN,
1065                 )
1066             captor.lastValue.onReceive(context, intent)
1067             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
1068         }
1069 
1070     @Test
1071     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNotNull_showSpn_spnNotNull_dataSpnNullnull1072     fun networkName_showPlmn_plmnNotNull_showSpn_spnNotNull_dataSpnNull() =
1073         testScope.runTest {
1074             val latest by collectLastValue(underTest.networkName)
1075             val captor = argumentCaptor<BroadcastReceiver>()
1076             verify(context).registerReceiver(captor.capture(), any())
1077             val intent =
1078                 spnIntent(
1079                     subId = SUB_1_ID,
1080                     showSpn = true,
1081                     spn = SPN,
1082                     dataSpn = null,
1083                     showPlmn = true,
1084                     plmn = PLMN,
1085                 )
1086             captor.lastValue.onReceive(context, intent)
1087             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
1088         }
1089 
1090     @Test
1091     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNotNull_showSpn_spnNull_dataSpnNotNull_flagOffnull1092     fun networkName_showPlmn_plmnNotNull_showSpn_spnNull_dataSpnNotNull_flagOff() =
1093         testScope.runTest {
1094             val latest by collectLastValue(underTest.networkName)
1095             val captor = argumentCaptor<BroadcastReceiver>()
1096             verify(context).registerReceiver(captor.capture(), any())
1097             val intent =
1098                 spnIntent(
1099                     subId = SUB_1_ID,
1100                     showSpn = true,
1101                     spn = null,
1102                     dataSpn = DATA_SPN,
1103                     showPlmn = true,
1104                     plmn = PLMN,
1105                 )
1106             captor.lastValue.onReceive(context, intent)
1107             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
1108         }
1109 
1110     @Test
networkName_showPlmn_noShowSPNnull1111     fun networkName_showPlmn_noShowSPN() =
1112         testScope.runTest {
1113             val latest by collectLastValue(underTest.networkName)
1114             val captor = argumentCaptor<BroadcastReceiver>()
1115             verify(context).registerReceiver(captor.capture(), any())
1116             val intent =
1117                 spnIntent(
1118                     subId = SUB_1_ID,
1119                     showSpn = false,
1120                     spn = SPN,
1121                     dataSpn = DATA_SPN,
1122                     showPlmn = true,
1123                     plmn = PLMN,
1124                 )
1125             captor.lastValue.onReceive(context, intent)
1126             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN"))
1127         }
1128 
1129     @Test
1130     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNull_showSpnnull1131     fun networkName_showPlmn_plmnNull_showSpn() =
1132         testScope.runTest {
1133             val latest by collectLastValue(underTest.networkName)
1134             val captor = argumentCaptor<BroadcastReceiver>()
1135             verify(context).registerReceiver(captor.capture(), any())
1136             val intent =
1137                 spnIntent(
1138                     subId = SUB_1_ID,
1139                     showSpn = true,
1140                     spn = SPN,
1141                     dataSpn = DATA_SPN,
1142                     showPlmn = true,
1143                     plmn = null,
1144                 )
1145             captor.lastValue.onReceive(context, intent)
1146             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$DATA_SPN"))
1147         }
1148 
1149     @Test
1150     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNull_showSpn_dataSpnNullnull1151     fun networkName_showPlmn_plmnNull_showSpn_dataSpnNull() =
1152         testScope.runTest {
1153             val latest by collectLastValue(underTest.networkName)
1154             val captor = argumentCaptor<BroadcastReceiver>()
1155             verify(context).registerReceiver(captor.capture(), any())
1156             val intent =
1157                 spnIntent(
1158                     subId = SUB_1_ID,
1159                     showSpn = true,
1160                     spn = SPN,
1161                     dataSpn = null,
1162                     showPlmn = true,
1163                     plmn = null,
1164                 )
1165             captor.lastValue.onReceive(context, intent)
1166             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$SPN"))
1167         }
1168 
1169     @Test
1170     @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNull_showSpn_bothSpnNullnull1171     fun networkName_showPlmn_plmnNull_showSpn_bothSpnNull() =
1172         testScope.runTest {
1173             val latest by collectLastValue(underTest.networkName)
1174             val captor = argumentCaptor<BroadcastReceiver>()
1175             verify(context).registerReceiver(captor.capture(), any())
1176             val intent =
1177                 spnIntent(
1178                     subId = SUB_1_ID,
1179                     showSpn = true,
1180                     spn = null,
1181                     dataSpn = null,
1182                     showPlmn = true,
1183                     plmn = null,
1184                 )
1185             captor.lastValue.onReceive(context, intent)
1186             assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
1187         }
1188 
1189     @Test
1190     @DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
networkName_showPlmn_plmnNull_showSpn_flagOffnull1191     fun networkName_showPlmn_plmnNull_showSpn_flagOff() =
1192         testScope.runTest {
1193             val latest by collectLastValue(underTest.networkName)
1194             val captor = argumentCaptor<BroadcastReceiver>()
1195             verify(context).registerReceiver(captor.capture(), any())
1196             val intent =
1197                 spnIntent(
1198                     subId = SUB_1_ID,
1199                     showSpn = true,
1200                     spn = SPN,
1201                     dataSpn = DATA_SPN,
1202                     showPlmn = true,
1203                     plmn = null,
1204                 )
1205             captor.lastValue.onReceive(context, intent)
1206             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$DATA_SPN"))
1207         }
1208 
1209     @Test
operatorAlphaShort_trackednull1210     fun operatorAlphaShort_tracked() =
1211         testScope.runTest {
1212             var latest: String? = null
1213 
1214             val job = underTest.operatorAlphaShort.onEach { latest = it }.launchIn(this)
1215 
1216             val shortName = "short name"
1217             val serviceState = ServiceState()
1218             serviceState.setOperatorName(
1219                 /* longName */ "long name",
1220                 /* shortName */ shortName,
1221                 /* numeric */ "12345",
1222             )
1223 
1224             getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
1225 
1226             assertThat(latest).isEqualTo(shortName)
1227 
1228             job.cancel()
1229         }
1230 
1231     @Test
isInService_notIwlannull1232     fun isInService_notIwlan() =
1233         testScope.runTest {
1234             var latest: Boolean? = null
1235             val job = underTest.isInService.onEach { latest = it }.launchIn(this)
1236 
1237             val nriInService =
1238                 NetworkRegistrationInfo.Builder()
1239                     .setDomain(DOMAIN_PS)
1240                     .setTransportType(TRANSPORT_TYPE_WWAN)
1241                     .setRegistrationState(REGISTRATION_STATE_HOME)
1242                     .build()
1243 
1244             getTelephonyCallbackForType<ServiceStateListener>()
1245                 .onServiceStateChanged(
1246                     ServiceState().also {
1247                         it.voiceRegState = STATE_IN_SERVICE
1248                         it.addNetworkRegistrationInfo(nriInService)
1249                     }
1250                 )
1251 
1252             assertThat(latest).isTrue()
1253 
1254             getTelephonyCallbackForType<ServiceStateListener>()
1255                 .onServiceStateChanged(
1256                     ServiceState().also {
1257                         it.voiceRegState = STATE_OUT_OF_SERVICE
1258                         it.addNetworkRegistrationInfo(nriInService)
1259                     }
1260                 )
1261             assertThat(latest).isTrue()
1262 
1263             val nriNotInService =
1264                 NetworkRegistrationInfo.Builder()
1265                     .setDomain(DOMAIN_PS)
1266                     .setTransportType(TRANSPORT_TYPE_WWAN)
1267                     .setRegistrationState(REGISTRATION_STATE_DENIED)
1268                     .build()
1269             getTelephonyCallbackForType<ServiceStateListener>()
1270                 .onServiceStateChanged(
1271                     ServiceState().also {
1272                         it.voiceRegState = STATE_OUT_OF_SERVICE
1273                         it.addNetworkRegistrationInfo(nriNotInService)
1274                     }
1275                 )
1276             assertThat(latest).isFalse()
1277 
1278             job.cancel()
1279         }
1280 
1281     @Test
isInService_isIwlan_voiceOutOfService_dataInServicenull1282     fun isInService_isIwlan_voiceOutOfService_dataInService() =
1283         testScope.runTest {
1284             var latest: Boolean? = null
1285             val job = underTest.isInService.onEach { latest = it }.launchIn(this)
1286 
1287             val iwlanData =
1288                 NetworkRegistrationInfo.Builder()
1289                     .setDomain(DOMAIN_PS)
1290                     .setTransportType(TRANSPORT_TYPE_WLAN)
1291                     .setRegistrationState(REGISTRATION_STATE_HOME)
1292                     .build()
1293             val serviceState =
1294                 ServiceState().also {
1295                     it.voiceRegState = STATE_OUT_OF_SERVICE
1296                     it.addNetworkRegistrationInfo(iwlanData)
1297                 }
1298 
1299             getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
1300             assertThat(latest).isFalse()
1301 
1302             job.cancel()
1303         }
1304 
1305     @Test
1306     @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
isNonTerrestrial_updatesFromCallback0null1307     fun isNonTerrestrial_updatesFromCallback0() =
1308         testScope.runTest {
1309             val latest by collectLastValue(underTest.isNonTerrestrial)
1310 
1311             // Starts out false
1312             assertThat(latest).isFalse()
1313 
1314             val callback = getTelephonyCallbackForType<CarrierRoamingNtnModeListener>()
1315 
1316             callback.onCarrierRoamingNtnModeChanged(true)
1317             assertThat(latest).isTrue()
1318 
1319             callback.onCarrierRoamingNtnModeChanged(false)
1320             assertThat(latest).isFalse()
1321         }
1322 
1323     @Test
numberOfLevels_usesCarrierConfignull1324     fun numberOfLevels_usesCarrierConfig() =
1325         testScope.runTest {
1326             var latest: Int? = null
1327             val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
1328 
1329             assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS)
1330 
1331             systemUiCarrierConfig.processNewCarrierConfig(
1332                 configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true)
1333             )
1334 
1335             assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS + 1)
1336 
1337             systemUiCarrierConfig.processNewCarrierConfig(
1338                 configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
1339             )
1340 
1341             assertThat(latest).isEqualTo(DEFAULT_NUM_LEVELS)
1342 
1343             job.cancel()
1344         }
1345 
1346     @Test
inflateSignalStrength_usesCarrierConfignull1347     fun inflateSignalStrength_usesCarrierConfig() =
1348         testScope.runTest {
1349             val latest by collectLastValue(underTest.inflateSignalStrength)
1350 
1351             assertThat(latest).isEqualTo(false)
1352 
1353             systemUiCarrierConfig.processNewCarrierConfig(
1354                 configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true)
1355             )
1356 
1357             assertThat(latest).isEqualTo(true)
1358 
1359             systemUiCarrierConfig.processNewCarrierConfig(
1360                 configWithOverride(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false)
1361             )
1362 
1363             assertThat(latest).isEqualTo(false)
1364         }
1365 
1366     @Test
allowNetworkSliceIndicator_exposesCarrierConfigValuenull1367     fun allowNetworkSliceIndicator_exposesCarrierConfigValue() =
1368         testScope.runTest {
1369             val latest by collectLastValue(underTest.allowNetworkSliceIndicator)
1370 
1371             systemUiCarrierConfig.processNewCarrierConfig(
1372                 configWithOverride(KEY_SHOW_5G_SLICE_ICON_BOOL, true)
1373             )
1374 
1375             assertThat(latest).isTrue()
1376 
1377             systemUiCarrierConfig.processNewCarrierConfig(
1378                 configWithOverride(KEY_SHOW_5G_SLICE_ICON_BOOL, false)
1379             )
1380 
1381             assertThat(latest).isFalse()
1382         }
1383 
1384     @Test
isAllowedDuringAirplaneMode_alwaysFalsenull1385     fun isAllowedDuringAirplaneMode_alwaysFalse() =
1386         testScope.runTest {
1387             val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
1388 
1389             assertThat(latest).isFalse()
1390         }
1391 
1392     @Test
hasPrioritizedCaps_defaultFalsenull1393     fun hasPrioritizedCaps_defaultFalse() {
1394         assertThat(underTest.hasPrioritizedNetworkCapabilities.value).isFalse()
1395     }
1396 
1397     @Test
hasPrioritizedCaps_trueWhenAvailablenull1398     fun hasPrioritizedCaps_trueWhenAvailable() =
1399         testScope.runTest {
1400             val latest by collectLastValue(underTest.hasPrioritizedNetworkCapabilities)
1401 
1402             val callback: NetworkCallback =
1403                 withArgCaptor<NetworkCallback> {
1404                     verify(connectivityManager).registerNetworkCallback(any(), capture())
1405                 }
1406 
1407             callback.onAvailable(mock())
1408 
1409             assertThat(latest).isTrue()
1410         }
1411 
1412     @Test
hasPrioritizedCaps_becomesFalseWhenNetworkLostnull1413     fun hasPrioritizedCaps_becomesFalseWhenNetworkLost() =
1414         testScope.runTest {
1415             val latest by collectLastValue(underTest.hasPrioritizedNetworkCapabilities)
1416 
1417             val callback: NetworkCallback =
1418                 withArgCaptor<NetworkCallback> {
1419                     verify(connectivityManager).registerNetworkCallback(any(), capture())
1420                 }
1421 
1422             callback.onAvailable(mock())
1423 
1424             assertThat(latest).isTrue()
1425 
1426             callback.onLost(mock())
1427 
1428             assertThat(latest).isFalse()
1429         }
1430 
getTelephonyCallbackForTypenull1431     private inline fun <reified T> getTelephonyCallbackForType(): T {
1432         return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
1433     }
1434 
carrierIdIntentnull1435     private fun carrierIdIntent(
1436         subId: Int = SUB_1_ID,
1437         carrierId: Int,
1438     ): Intent =
1439         Intent(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED).apply {
1440             putExtra(EXTRA_SUBSCRIPTION_ID, subId)
1441             putExtra(EXTRA_CARRIER_ID, carrierId)
1442         }
1443 
spnIntentnull1444     private fun spnIntent(
1445         subId: Int = SUB_1_ID,
1446         showSpn: Boolean = true,
1447         spn: String? = SPN,
1448         dataSpn: String? = DATA_SPN,
1449         showPlmn: Boolean = true,
1450         plmn: String? = PLMN,
1451     ): Intent =
1452         Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED).apply {
1453             putExtra(EXTRA_SUBSCRIPTION_INDEX, subId)
1454             putExtra(EXTRA_SHOW_SPN, showSpn)
1455             putExtra(EXTRA_SPN, spn)
1456             putExtra(EXTRA_DATA_SPN, dataSpn)
1457             putExtra(EXTRA_SHOW_PLMN, showPlmn)
1458             putExtra(EXTRA_PLMN, plmn)
1459         }
1460 
1461     companion object {
1462         private const val SUB_1_ID = 1
1463 
1464         private const val DEFAULT_NAME = "Fake Mobile Network"
1465         private val DEFAULT_NAME_MODEL = NetworkNameModel.Default(DEFAULT_NAME)
1466         private const val SEP = "-"
1467 
1468         private const val SPN = "testSpn"
1469         private const val DATA_SPN = "testDataSpn"
1470         private const val PLMN = "testPlmn"
1471     }
1472 }
1473