• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.domain.interactor
18 
19 import android.telephony.CellSignalStrength
20 import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
21 import androidx.test.filters.SmallTest
22 import com.android.settingslib.SignalIcon.MobileIconGroup
23 import com.android.settingslib.mobile.TelephonyIcons
24 import com.android.systemui.SysuiTestCase
25 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
26 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
27 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
28 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
29 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
30 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
31 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FIVE_G_OVERRIDE
32 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FOUR_G
33 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.THREE_G
34 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
35 import com.android.systemui.util.mockito.mock
36 import com.google.common.truth.Truth.assertThat
37 import kotlinx.coroutines.CoroutineScope
38 import kotlinx.coroutines.Dispatchers
39 import kotlinx.coroutines.flow.launchIn
40 import kotlinx.coroutines.flow.onEach
41 import kotlinx.coroutines.runBlocking
42 import kotlinx.coroutines.yield
43 import org.junit.Before
44 import org.junit.Test
45 
46 @SmallTest
47 class MobileIconInteractorTest : SysuiTestCase() {
48     private lateinit var underTest: MobileIconInteractor
49     private val mobileMappingsProxy = FakeMobileMappingsProxy()
50     private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())
51     private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock())
52 
53     private val scope = CoroutineScope(IMMEDIATE)
54 
55     @Before
setUpnull56     fun setUp() {
57         underTest =
58             MobileIconInteractorImpl(
59                 scope,
60                 mobileIconsInteractor.activeDataConnectionHasDataEnabled,
61                 mobileIconsInteractor.alwaysShowDataRatIcon,
62                 mobileIconsInteractor.alwaysUseCdmaLevel,
63                 mobileIconsInteractor.defaultMobileNetworkConnectivity,
64                 mobileIconsInteractor.defaultMobileIconMapping,
65                 mobileIconsInteractor.defaultMobileIconGroup,
66                 mobileIconsInteractor.defaultDataSubId,
67                 mobileIconsInteractor.isDefaultConnectionFailed,
68                 mobileIconsInteractor.isForceHidden,
69                 connectionRepository,
70             )
71     }
72 
73     @Test
gsm_level_default_unknownnull74     fun gsm_level_default_unknown() =
75         runBlocking(IMMEDIATE) {
76             connectionRepository.isGsm.value = true
77 
78             var latest: Int? = null
79             val job = underTest.level.onEach { latest = it }.launchIn(this)
80 
81             assertThat(latest).isEqualTo(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
82 
83             job.cancel()
84         }
85 
86     @Test
gsm_usesGsmLevelnull87     fun gsm_usesGsmLevel() =
88         runBlocking(IMMEDIATE) {
89             connectionRepository.isGsm.value = true
90             connectionRepository.primaryLevel.value = GSM_LEVEL
91             connectionRepository.cdmaLevel.value = CDMA_LEVEL
92 
93             var latest: Int? = null
94             val job = underTest.level.onEach { latest = it }.launchIn(this)
95 
96             assertThat(latest).isEqualTo(GSM_LEVEL)
97 
98             job.cancel()
99         }
100 
101     @Test
gsm_alwaysShowCdmaTrue_stillUsesGsmLevelnull102     fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() =
103         runBlocking(IMMEDIATE) {
104             connectionRepository.isGsm.value = true
105             connectionRepository.primaryLevel.value = GSM_LEVEL
106             connectionRepository.cdmaLevel.value = CDMA_LEVEL
107             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
108 
109             var latest: Int? = null
110             val job = underTest.level.onEach { latest = it }.launchIn(this)
111 
112             assertThat(latest).isEqualTo(GSM_LEVEL)
113 
114             job.cancel()
115         }
116 
117     @Test
notGsm_level_default_unknownnull118     fun notGsm_level_default_unknown() =
119         runBlocking(IMMEDIATE) {
120             connectionRepository.isGsm.value = false
121 
122             var latest: Int? = null
123             val job = underTest.level.onEach { latest = it }.launchIn(this)
124 
125             assertThat(latest).isEqualTo(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
126             job.cancel()
127         }
128 
129     @Test
notGsm_alwaysShowCdmaTrue_usesCdmaLevelnull130     fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() =
131         runBlocking(IMMEDIATE) {
132             connectionRepository.isGsm.value = false
133             connectionRepository.primaryLevel.value = GSM_LEVEL
134             connectionRepository.cdmaLevel.value = CDMA_LEVEL
135             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
136 
137             var latest: Int? = null
138             val job = underTest.level.onEach { latest = it }.launchIn(this)
139 
140             assertThat(latest).isEqualTo(CDMA_LEVEL)
141 
142             job.cancel()
143         }
144 
145     @Test
notGsm_alwaysShowCdmaFalse_usesPrimaryLevelnull146     fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() =
147         runBlocking(IMMEDIATE) {
148             connectionRepository.isGsm.value = false
149             connectionRepository.primaryLevel.value = GSM_LEVEL
150             connectionRepository.cdmaLevel.value = CDMA_LEVEL
151             mobileIconsInteractor.alwaysUseCdmaLevel.value = false
152 
153             var latest: Int? = null
154             val job = underTest.level.onEach { latest = it }.launchIn(this)
155 
156             assertThat(latest).isEqualTo(GSM_LEVEL)
157 
158             job.cancel()
159         }
160 
161     @Test
numberOfLevels_comesFromReponull162     fun numberOfLevels_comesFromRepo() =
163         runBlocking(IMMEDIATE) {
164             var latest: Int? = null
165             val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this)
166 
167             connectionRepository.numberOfLevels.value = 5
168             assertThat(latest).isEqualTo(5)
169 
170             connectionRepository.numberOfLevels.value = 4
171             assertThat(latest).isEqualTo(4)
172 
173             job.cancel()
174         }
175 
176     @Test
iconGroup_three_gnull177     fun iconGroup_three_g() =
178         runBlocking(IMMEDIATE) {
179             connectionRepository.resolvedNetworkType.value =
180                 DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
181 
182             var latest: MobileIconGroup? = null
183             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
184 
185             assertThat(latest).isEqualTo(TelephonyIcons.THREE_G)
186 
187             job.cancel()
188         }
189 
190     @Test
iconGroup_updates_on_changenull191     fun iconGroup_updates_on_change() =
192         runBlocking(IMMEDIATE) {
193             connectionRepository.resolvedNetworkType.value =
194                 DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
195 
196             var latest: MobileIconGroup? = null
197             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
198 
199             connectionRepository.resolvedNetworkType.value =
200                 DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G))
201             yield()
202 
203             assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G)
204 
205             job.cancel()
206         }
207 
208     @Test
iconGroup_5g_override_typenull209     fun iconGroup_5g_override_type() =
210         runBlocking(IMMEDIATE) {
211             connectionRepository.resolvedNetworkType.value =
212                 OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
213 
214             var latest: MobileIconGroup? = null
215             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
216 
217             assertThat(latest).isEqualTo(TelephonyIcons.NR_5G)
218 
219             job.cancel()
220         }
221 
222     @Test
iconGroup_default_if_no_lookupnull223     fun iconGroup_default_if_no_lookup() =
224         runBlocking(IMMEDIATE) {
225             connectionRepository.resolvedNetworkType.value =
226                 DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN))
227 
228             var latest: MobileIconGroup? = null
229             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
230 
231             assertThat(latest).isEqualTo(FakeMobileIconsInteractor.DEFAULT_ICON)
232 
233             job.cancel()
234         }
235 
236     @Test
iconGroup_carrierMerged_usesOverridenull237     fun iconGroup_carrierMerged_usesOverride() =
238         runBlocking(IMMEDIATE) {
239             connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType
240 
241             var latest: MobileIconGroup? = null
242             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
243 
244             assertThat(latest).isEqualTo(CarrierMergedNetworkType.iconGroupOverride)
245 
246             job.cancel()
247         }
248 
249     @Test
icon group - checks default datanull250     fun `icon group - checks default data`() =
251         runBlocking(IMMEDIATE) {
252             mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID
253             connectionRepository.resolvedNetworkType.value =
254                 DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
255 
256             var latest: MobileIconGroup? = null
257             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
258 
259             assertThat(latest).isEqualTo(TelephonyIcons.THREE_G)
260 
261             // Default data sub id changes to something else
262             mobileIconsInteractor.defaultDataSubId.value = 123
263             yield()
264 
265             assertThat(latest).isEqualTo(TelephonyIcons.NOT_DEFAULT_DATA)
266 
267             job.cancel()
268         }
269 
270     @Test
alwaysShowDataRatIcon_matchesParentnull271     fun alwaysShowDataRatIcon_matchesParent() =
272         runBlocking(IMMEDIATE) {
273             var latest: Boolean? = null
274             val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this)
275 
276             mobileIconsInteractor.alwaysShowDataRatIcon.value = true
277             assertThat(latest).isTrue()
278 
279             mobileIconsInteractor.alwaysShowDataRatIcon.value = false
280             assertThat(latest).isFalse()
281 
282             job.cancel()
283         }
284 
285     @Test
alwaysUseCdmaLevel_matchesParentnull286     fun alwaysUseCdmaLevel_matchesParent() =
287         runBlocking(IMMEDIATE) {
288             var latest: Boolean? = null
289             val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this)
290 
291             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
292             assertThat(latest).isTrue()
293 
294             mobileIconsInteractor.alwaysUseCdmaLevel.value = false
295             assertThat(latest).isFalse()
296 
297             job.cancel()
298         }
299 
300     @Test
test_isDefaultDataEnabled_matchesParentnull301     fun test_isDefaultDataEnabled_matchesParent() =
302         runBlocking(IMMEDIATE) {
303             var latest: Boolean? = null
304             val job = underTest.isDefaultDataEnabled.onEach { latest = it }.launchIn(this)
305 
306             mobileIconsInteractor.activeDataConnectionHasDataEnabled.value = true
307             assertThat(latest).isTrue()
308 
309             mobileIconsInteractor.activeDataConnectionHasDataEnabled.value = false
310             assertThat(latest).isFalse()
311 
312             job.cancel()
313         }
314 
315     @Test
test_isDefaultConnectionFailed_matchedParentnull316     fun test_isDefaultConnectionFailed_matchedParent() =
317         runBlocking(IMMEDIATE) {
318             val job = underTest.isDefaultConnectionFailed.launchIn(this)
319 
320             mobileIconsInteractor.isDefaultConnectionFailed.value = false
321             assertThat(underTest.isDefaultConnectionFailed.value).isFalse()
322 
323             mobileIconsInteractor.isDefaultConnectionFailed.value = true
324             assertThat(underTest.isDefaultConnectionFailed.value).isTrue()
325 
326             job.cancel()
327         }
328 
329     @Test
dataState_connectednull330     fun dataState_connected() =
331         runBlocking(IMMEDIATE) {
332             var latest: Boolean? = null
333             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
334 
335             connectionRepository.dataConnectionState.value = DataConnectionState.Connected
336             yield()
337 
338             assertThat(latest).isTrue()
339 
340             job.cancel()
341         }
342 
343     @Test
dataState_notConnectednull344     fun dataState_notConnected() =
345         runBlocking(IMMEDIATE) {
346             var latest: Boolean? = null
347             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
348 
349             connectionRepository.dataConnectionState.value = DataConnectionState.Disconnected
350 
351             assertThat(latest).isFalse()
352 
353             job.cancel()
354         }
355 
356     @Test
isInService - uses repository valuenull357     fun `isInService - uses repository value`() =
358         runBlocking(IMMEDIATE) {
359             var latest: Boolean? = null
360             val job = underTest.isInService.onEach { latest = it }.launchIn(this)
361 
362             connectionRepository.isInService.value = true
363 
364             assertThat(latest).isTrue()
365 
366             connectionRepository.isInService.value = false
367 
368             assertThat(latest).isFalse()
369 
370             job.cancel()
371         }
372 
373     @Test
roaming - is gsm - uses connection modelnull374     fun `roaming - is gsm - uses connection model`() =
375         runBlocking(IMMEDIATE) {
376             var latest: Boolean? = null
377             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
378 
379             connectionRepository.cdmaRoaming.value = true
380             connectionRepository.isGsm.value = true
381             connectionRepository.isRoaming.value = false
382             yield()
383 
384             assertThat(latest).isFalse()
385 
386             connectionRepository.isRoaming.value = true
387             yield()
388 
389             assertThat(latest).isTrue()
390 
391             job.cancel()
392         }
393 
394     @Test
roaming - is cdma - uses cdma roaming bitnull395     fun `roaming - is cdma - uses cdma roaming bit`() =
396         runBlocking(IMMEDIATE) {
397             var latest: Boolean? = null
398             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
399 
400             connectionRepository.cdmaRoaming.value = false
401             connectionRepository.isGsm.value = false
402             connectionRepository.isRoaming.value = true
403             yield()
404 
405             assertThat(latest).isFalse()
406 
407             connectionRepository.cdmaRoaming.value = true
408             connectionRepository.isGsm.value = false
409             connectionRepository.isRoaming.value = false
410             yield()
411 
412             assertThat(latest).isTrue()
413 
414             job.cancel()
415         }
416 
417     @Test
roaming - false while carrierNetworkChangeActivenull418     fun `roaming - false while carrierNetworkChangeActive`() =
419         runBlocking(IMMEDIATE) {
420             var latest: Boolean? = null
421             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
422 
423             connectionRepository.cdmaRoaming.value = true
424             connectionRepository.isGsm.value = false
425             connectionRepository.isRoaming.value = true
426             connectionRepository.carrierNetworkChangeActive.value = true
427             yield()
428 
429             assertThat(latest).isFalse()
430 
431             connectionRepository.cdmaRoaming.value = true
432             connectionRepository.isGsm.value = true
433             yield()
434 
435             assertThat(latest).isFalse()
436 
437             job.cancel()
438         }
439 
440     @Test
network name - uses operatorAlphaShot when non null and repo is defaultnull441     fun `network name - uses operatorAlphaShot when non null and repo is default`() =
442         runBlocking(IMMEDIATE) {
443             var latest: NetworkNameModel? = null
444             val job = underTest.networkName.onEach { latest = it }.launchIn(this)
445 
446             val testOperatorName = "operatorAlphaShort"
447 
448             // Default network name, operator name is non-null, uses the operator name
449             connectionRepository.networkName.value = DEFAULT_NAME
450             connectionRepository.operatorAlphaShort.value = testOperatorName
451             yield()
452 
453             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName))
454 
455             // Default network name, operator name is null, uses the default
456             connectionRepository.operatorAlphaShort.value = null
457             yield()
458 
459             assertThat(latest).isEqualTo(DEFAULT_NAME)
460 
461             // Derived network name, operator name non-null, uses the derived name
462             connectionRepository.networkName.value = DERIVED_NAME
463             connectionRepository.operatorAlphaShort.value = testOperatorName
464             yield()
465 
466             assertThat(latest).isEqualTo(DERIVED_NAME)
467 
468             job.cancel()
469         }
470 
471     @Test
isForceHidden_matchesParentnull472     fun isForceHidden_matchesParent() =
473         runBlocking(IMMEDIATE) {
474             var latest: Boolean? = null
475             val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
476 
477             mobileIconsInteractor.isForceHidden.value = true
478             assertThat(latest).isTrue()
479 
480             mobileIconsInteractor.isForceHidden.value = false
481             assertThat(latest).isFalse()
482 
483             job.cancel()
484         }
485 
486     companion object {
487         private val IMMEDIATE = Dispatchers.Main.immediate
488 
489         private const val GSM_LEVEL = 1
490         private const val CDMA_LEVEL = 2
491 
492         private const val SUB_1_ID = 1
493 
494         private val DEFAULT_NAME = NetworkNameModel.Default("test default name")
495         private val DERIVED_NAME = NetworkNameModel.IntentDerived("test derived name")
496     }
497 }
498