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