• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2025 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 androidx.test.ext.junit.runners.AndroidJUnit4
20 import androidx.test.filters.SmallTest
21 import com.android.settingslib.SignalIcon
22 import com.android.settingslib.mobile.MobileMappings
23 import com.android.settingslib.mobile.TelephonyIcons
24 import com.android.systemui.KairosBuilder
25 import com.android.systemui.flags.featureFlagsClassic
26 import com.android.systemui.kairos.BuildScope
27 import com.android.systemui.kairos.Events
28 import com.android.systemui.kairos.ExperimentalKairosApi
29 import com.android.systemui.kairos.Incremental
30 import com.android.systemui.kairos.State
31 import com.android.systemui.kairos.activateKairosActivatable
32 import com.android.systemui.kairos.asIncremental
33 import com.android.systemui.kairos.buildSpec
34 import com.android.systemui.kairos.kairos
35 import com.android.systemui.kairos.map
36 import com.android.systemui.kairos.mapValues
37 import com.android.systemui.kairos.stateOf
38 import com.android.systemui.kairosBuilder
39 import com.android.systemui.kosmos.Kosmos
40 import com.android.systemui.kosmos.applicationCoroutineScope
41 import com.android.systemui.kosmos.runCurrent
42 import com.android.systemui.log.table.TableLogBuffer
43 import com.android.systemui.log.table.tableLogBufferFactory
44 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
45 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
46 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
47 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
48 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
49 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepositoryKairos
50 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
51 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepositoryKairos
52 import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileMappingsProxy
53 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
54 import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository
55 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
56 import org.junit.runner.RunWith
57 import org.mockito.kotlin.mock
58 
59 @OptIn(ExperimentalKairosApi::class)
60 @SmallTest
61 @RunWith(AndroidJUnit4::class)
62 class MobileIconsInteractorKairosAdapterTest : MobileIconsInteractorTestBase() {
63     override fun Kosmos.createInteractor(): MobileIconsInteractor {
64         val userSetupRepo = FakeUserSetupRepository()
65         val repoK =
66             MobileConnectionsRepoWrapper(connectionsRepository).also {
67                 activateKairosActivatable(it)
68             }
69         val kairosInteractor =
70             MobileIconsInteractorKairosImpl(
71                     mobileConnectionsRepo = repoK,
72                     carrierConfigTracker = carrierConfigTracker,
73                     tableLogger = mock(),
74                     connectivityRepository = connectivityRepository,
75                     userSetupRepo = userSetupRepo,
76                     context = context,
77                     featureFlagsClassic = featureFlagsClassic,
78                 )
79                 .also { activateKairosActivatable(it) }
80         return MobileIconsInteractorKairosAdapter(
81                 kairosInteractor = kairosInteractor,
82                 repo = connectionsRepository,
83                 repoK = repoK,
84                 kairosNetwork = kairos,
85                 scope = applicationCoroutineScope,
86                 context = context,
87                 mobileMappingsProxy = mobileMappingsProxy,
88                 userSetupRepo = userSetupRepo,
89                 logFactory = tableLogBufferFactory,
90             )
91             .also {
92                 activateKairosActivatable(it)
93                 runCurrent()
94             }
95     }
96 
97     /** Allows us to wrap a (likely fake) MobileConnectionsRepository into a Kairos version. */
98     private class MobileConnectionsRepoWrapper(val unwrapped: MobileConnectionsRepository) :
99         MobileConnectionsRepositoryKairos, KairosBuilder by kairosBuilder() {
100 
101         override val mobileConnectionsBySubId: Incremental<Int, MobileConnectionRepositoryKairos> =
102             buildIncremental {
103                 unwrapped.subscriptions
104                     .toState()
105                     .map { it.associate { it.subscriptionId to Unit } }
106                     .asIncremental()
107                     .mapValues { (subId, _) ->
108                         buildSpec { wrapRepo(unwrapped.getRepoForSubId(subId)) }
109                     }
110                     .applyLatestSpecForKey()
111             }
112         override val subscriptions: State<Collection<SubscriptionModel>> = buildState {
113             unwrapped.subscriptions.toState()
114         }
115         override val activeMobileDataSubscriptionId: State<Int?> = buildState {
116             unwrapped.activeMobileDataSubscriptionId.toState()
117         }
118         override val activeMobileDataRepository: State<MobileConnectionRepositoryKairos?> =
119             buildState {
120                 unwrapped.activeMobileDataRepository.toState().mapLatestBuild {
121                     it?.let { wrapRepo(it) }
122                 }
123             }
124         override val activeSubChangedInGroupEvent: Events<Unit> = buildEvents {
125             unwrapped.activeSubChangedInGroupEvent.toEvents()
126         }
127         override val defaultDataSubId: State<Int?> = buildState {
128             unwrapped.defaultDataSubId.toState()
129         }
130         override val mobileIsDefault: State<Boolean> = buildState {
131             unwrapped.mobileIsDefault.toState()
132         }
133         override val hasCarrierMergedConnection: State<Boolean> = buildState {
134             unwrapped.hasCarrierMergedConnection.toState(false)
135         }
136         override val defaultConnectionIsValidated: State<Boolean> = buildState {
137             unwrapped.defaultConnectionIsValidated.toState()
138         }
139         override val defaultDataSubRatConfig: State<MobileMappings.Config> = buildState {
140             unwrapped.defaultDataSubRatConfig.toState()
141         }
142         override val defaultMobileIconMapping: State<Map<String, SignalIcon.MobileIconGroup>> =
143             buildState {
144                 unwrapped.defaultMobileIconMapping.toState(emptyMap())
145             }
146         override val defaultMobileIconGroup: State<SignalIcon.MobileIconGroup> = buildState {
147             unwrapped.defaultMobileIconGroup.toState(TelephonyIcons.THREE_G)
148         }
149         override val isDeviceEmergencyCallCapable: State<Boolean> = buildState {
150             unwrapped.isDeviceEmergencyCallCapable.toState()
151         }
152         override val isAnySimSecure: State<Boolean> = buildState {
153             unwrapped.isDeviceEmergencyCallCapable.toState()
154         }
155         override val isInEcmMode: State<Boolean> = stateOf(false)
156     }
157 
158     private class MobileConnectionRepoWrapper(
159         override val subId: Int,
160         override val carrierId: State<Int>,
161         override val inflateSignalStrength: State<Boolean>,
162         override val allowNetworkSliceIndicator: State<Boolean>,
163         override val tableLogBuffer: TableLogBuffer,
164         override val isEmergencyOnly: State<Boolean>,
165         override val isRoaming: State<Boolean>,
166         override val operatorAlphaShort: State<String?>,
167         override val isInService: State<Boolean>,
168         override val isNonTerrestrial: State<Boolean>,
169         override val isGsm: State<Boolean>,
170         override val cdmaLevel: State<Int>,
171         override val primaryLevel: State<Int>,
172         override val satelliteLevel: State<Int>,
173         override val dataConnectionState: State<DataConnectionState>,
174         override val dataActivityDirection: State<DataActivityModel>,
175         override val carrierNetworkChangeActive: State<Boolean>,
176         override val resolvedNetworkType: State<ResolvedNetworkType>,
177         override val numberOfLevels: State<Int>,
178         override val dataEnabled: State<Boolean>,
179         override val cdmaRoaming: State<Boolean>,
180         override val networkName: State<NetworkNameModel>,
181         override val carrierName: State<NetworkNameModel>,
182         override val isAllowedDuringAirplaneMode: State<Boolean>,
183         override val hasPrioritizedNetworkCapabilities: State<Boolean>,
184         override val isInEcmMode: State<Boolean>,
185     ) : MobileConnectionRepositoryKairos
186 
187     companion object {
188         /** Allows us to wrap a (likely fake) MobileConnectionRepository into a Kairos version. */
189         fun BuildScope.wrapRepo(
190             conn: MobileConnectionRepository
191         ): MobileConnectionRepositoryKairos =
192             with(conn) {
193                 MobileConnectionRepoWrapper(
194                     subId = subId,
195                     carrierId = carrierId.toState(),
196                     inflateSignalStrength = inflateSignalStrength.toState(),
197                     allowNetworkSliceIndicator = allowNetworkSliceIndicator.toState(),
198                     tableLogBuffer = tableLogBuffer,
199                     isEmergencyOnly = isEmergencyOnly.toState(),
200                     isRoaming = isRoaming.toState(),
201                     operatorAlphaShort = operatorAlphaShort.toState(),
202                     isInService = isInService.toState(),
203                     isNonTerrestrial = isNonTerrestrial.toState(),
204                     isGsm = isGsm.toState(),
205                     cdmaLevel = cdmaLevel.toState(),
206                     primaryLevel = primaryLevel.toState(),
207                     satelliteLevel = satelliteLevel.toState(),
208                     dataConnectionState = dataConnectionState.toState(),
209                     dataActivityDirection = dataActivityDirection.toState(),
210                     carrierNetworkChangeActive = carrierNetworkChangeActive.toState(),
211                     resolvedNetworkType = resolvedNetworkType.toState(),
212                     numberOfLevels = numberOfLevels.toState(),
213                     dataEnabled = dataEnabled.toState(),
214                     cdmaRoaming = cdmaRoaming.toState(),
215                     networkName = networkName.toState(),
216                     carrierName = carrierName.toState(),
217                     isAllowedDuringAirplaneMode = isAllowedDuringAirplaneMode.toState(),
218                     hasPrioritizedNetworkCapabilities = hasPrioritizedNetworkCapabilities.toState(),
219                     isInEcmMode = stateOf(false),
220                 )
221             }
222     }
223 }
224