• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
18 
19 import android.telephony.CellSignalStrength
20 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
21 import android.telephony.TelephonyManager
22 import com.android.systemui.log.table.TableLogBuffer
23 import com.android.systemui.log.table.logDiffsForTable
24 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
25 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
26 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
27 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
28 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
29 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
30 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_ID
31 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_NETWORK_CHANGE
32 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CDMA_LEVEL
33 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
34 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM
35 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE
36 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_NTN
37 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
38 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
39 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING
40 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_SATELLITE_LEVEL
41 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
42 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
43 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
44 import kotlinx.coroutines.CoroutineScope
45 import kotlinx.coroutines.flow.MutableStateFlow
46 import kotlinx.coroutines.flow.SharingStarted
47 import kotlinx.coroutines.flow.StateFlow
48 import kotlinx.coroutines.flow.map
49 import kotlinx.coroutines.flow.stateIn
50 
51 /**
52  * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using
53  * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular
54  * [MutableStateFlow] while still logging all of the inputs in the same manor as the production
55  * repos.
56  */
57 class DemoMobileConnectionRepository(
58     override val subId: Int,
59     override val tableLogBuffer: TableLogBuffer,
60     val scope: CoroutineScope,
61 ) : MobileConnectionRepository {
62     private val _carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
63     override val carrierId =
64         _carrierId
65             .logDiffsForTable(
66                 tableLogBuffer,
67                 columnName = COL_CARRIER_ID,
68                 initialValue = _carrierId.value,
69             )
70             .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value)
71 
72     private val _inflateSignalStrength: MutableStateFlow<Boolean> = MutableStateFlow(false)
73     override val inflateSignalStrength =
74         _inflateSignalStrength
75             .logDiffsForTable(
76                 tableLogBuffer,
77                 columnName = "inflate",
78                 initialValue = _inflateSignalStrength.value,
79             )
80             .stateIn(scope, SharingStarted.WhileSubscribed(), _inflateSignalStrength.value)
81 
82     // I don't see a reason why we would turn the config off for demo mode.
83     override val allowNetworkSliceIndicator = MutableStateFlow(true)
84 
85     private val _isEmergencyOnly = MutableStateFlow(false)
86     override val isEmergencyOnly =
87         _isEmergencyOnly
88             .logDiffsForTable(
89                 tableLogBuffer,
90                 columnName = COL_EMERGENCY,
91                 initialValue = _isEmergencyOnly.value,
92             )
93             .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)
94 
95     private val _isRoaming = MutableStateFlow(false)
96     override val isRoaming =
97         _isRoaming
98             .logDiffsForTable(
99                 tableLogBuffer,
100                 columnName = COL_ROAMING,
101                 initialValue = _isRoaming.value,
102             )
103             .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)
104 
105     private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
106     override val operatorAlphaShort =
107         _operatorAlphaShort
108             .logDiffsForTable(
109                 tableLogBuffer,
110                 columnName = COL_OPERATOR,
111                 initialValue = _operatorAlphaShort.value,
112             )
113             .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)
114 
115     private val _isInService = MutableStateFlow(false)
116     override val isInService =
117         _isInService
118             .logDiffsForTable(
119                 tableLogBuffer,
120                 columnName = COL_IS_IN_SERVICE,
121                 initialValue = _isInService.value,
122             )
123             .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)
124 
125     private val _isNonTerrestrial = MutableStateFlow(false)
126     override val isNonTerrestrial =
127         _isNonTerrestrial
128             .logDiffsForTable(
129                 tableLogBuffer,
130                 columnName = COL_IS_NTN,
131                 initialValue = _isNonTerrestrial.value,
132             )
133             .stateIn(scope, SharingStarted.WhileSubscribed(), _isNonTerrestrial.value)
134 
135     private val _isGsm = MutableStateFlow(false)
136     override val isGsm =
137         _isGsm
138             .logDiffsForTable(tableLogBuffer, columnName = COL_IS_GSM, initialValue = _isGsm.value)
139             .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)
140 
141     private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
142     override val cdmaLevel =
143         _cdmaLevel
144             .logDiffsForTable(
145                 tableLogBuffer,
146                 columnName = COL_CDMA_LEVEL,
147                 initialValue = _cdmaLevel.value,
148             )
149             .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)
150 
151     private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
152     override val primaryLevel =
153         _primaryLevel
154             .logDiffsForTable(
155                 tableLogBuffer,
156                 columnName = COL_PRIMARY_LEVEL,
157                 initialValue = _primaryLevel.value,
158             )
159             .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)
160 
161     private val _satelliteLevel = MutableStateFlow(0)
162     override val satelliteLevel: StateFlow<Int> =
163         _satelliteLevel
164             .logDiffsForTable(
165                 tableLogBuffer,
166                 columnName = COL_SATELLITE_LEVEL,
167                 initialValue = _satelliteLevel.value,
168             )
169             .stateIn(scope, SharingStarted.WhileSubscribed(), _satelliteLevel.value)
170 
171     private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
172     override val dataConnectionState =
173         _dataConnectionState
174             .logDiffsForTable(tableLogBuffer, initialValue = _dataConnectionState.value)
175             .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value)
176 
177     private val _dataActivityDirection =
178         MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
179     override val dataActivityDirection =
180         _dataActivityDirection
181             .logDiffsForTable(tableLogBuffer, initialValue = _dataActivityDirection.value)
182             .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)
183 
184     private val _carrierNetworkChangeActive = MutableStateFlow(false)
185     override val carrierNetworkChangeActive =
186         _carrierNetworkChangeActive
187             .logDiffsForTable(
188                 tableLogBuffer,
189                 columnName = COL_CARRIER_NETWORK_CHANGE,
190                 initialValue = _carrierNetworkChangeActive.value,
191             )
192             .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)
193 
194     private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
195         MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
196     override val resolvedNetworkType =
197         _resolvedNetworkType
198             .logDiffsForTable(tableLogBuffer, initialValue = _resolvedNetworkType.value)
199             .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
200 
201     override val numberOfLevels =
202         _inflateSignalStrength
203             .map { shouldInflate ->
204                 if (shouldInflate) {
205                     DEFAULT_NUM_LEVELS + 1
206                 } else {
207                     DEFAULT_NUM_LEVELS
208                 }
209             }
210             .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
211 
212     override val dataEnabled = MutableStateFlow(true)
213 
214     override val cdmaRoaming = MutableStateFlow(false)
215 
216     override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived(DEMO_CARRIER_NAME))
217 
218     override val carrierName =
219         MutableStateFlow(NetworkNameModel.SubscriptionDerived(DEMO_CARRIER_NAME))
220 
221     override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
222 
223     override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false)
224 
225     override suspend fun isInEcmMode(): Boolean = false
226 
227     /**
228      * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
229      * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
230      * repository.
231      */
232     fun processDemoMobileEvent(
233         event: FakeNetworkEventModel.Mobile,
234         resolvedNetworkType: ResolvedNetworkType,
235     ) {
236         // This is always true here, because we split out disabled states at the data-source level
237         dataEnabled.value = true
238         networkName.value = NetworkNameModel.IntentDerived(event.name)
239         carrierName.value = NetworkNameModel.SubscriptionDerived("${event.name} ${event.subId}")
240 
241         _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID
242 
243         _inflateSignalStrength.value = event.inflateStrength
244 
245         cdmaRoaming.value = event.roaming
246         _isRoaming.value = event.roaming
247         // TODO(b/261029387): not yet supported
248         _isEmergencyOnly.value = false
249         _operatorAlphaShort.value = event.name
250         _isInService.value = (event.level ?: 0) > 0
251         // TODO(b/261029387): not yet supported
252         _isGsm.value = false
253         _cdmaLevel.value = event.level ?: 0
254         _primaryLevel.value = event.level ?: 0
255         // TODO(b/261029387): not yet supported
256         _dataConnectionState.value = DataConnectionState.Connected
257         _dataActivityDirection.value =
258             (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
259         _carrierNetworkChangeActive.value = event.carrierNetworkChange
260         _resolvedNetworkType.value = resolvedNetworkType
261         _isNonTerrestrial.value = event.ntn
262 
263         isAllowedDuringAirplaneMode.value = false
264         hasPrioritizedNetworkCapabilities.value = event.slice
265     }
266 
267     fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
268         // This is always true here, because we split out disabled states at the data-source level
269         dataEnabled.value = true
270         networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
271         carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME)
272         // TODO(b/276943904): is carrierId a thing with carrier merged networks?
273         _carrierId.value = INVALID_SUBSCRIPTION_ID
274         cdmaRoaming.value = false
275         _primaryLevel.value = event.level
276         _cdmaLevel.value = event.level
277         _dataActivityDirection.value = event.activity.toMobileDataActivityModel()
278 
279         // These fields are always the same for carrier-merged networks
280         _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType
281         _dataConnectionState.value = DataConnectionState.Connected
282         _isRoaming.value = false
283         _isEmergencyOnly.value = false
284         _operatorAlphaShort.value = null
285         _isInService.value = true
286         _isGsm.value = false
287         _carrierNetworkChangeActive.value = false
288         isAllowedDuringAirplaneMode.value = true
289         hasPrioritizedNetworkCapabilities.value = false
290     }
291 
292     companion object {
293         private const val DEMO_CARRIER_NAME = "Demo Carrier"
294         private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
295     }
296 }
297