1 /* 2 * 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_OPERATOR 37 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL 38 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING 39 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel 40 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel 41 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel 42 import kotlinx.coroutines.CoroutineScope 43 import kotlinx.coroutines.flow.MutableStateFlow 44 import kotlinx.coroutines.flow.SharingStarted 45 import kotlinx.coroutines.flow.stateIn 46 47 /** 48 * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using 49 * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular 50 * [MutableStateFlow] while still logging all of the inputs in the same manor as the production 51 * repos. 52 */ 53 class DemoMobileConnectionRepository( 54 override val subId: Int, 55 override val tableLogBuffer: TableLogBuffer, 56 val scope: CoroutineScope, 57 ) : MobileConnectionRepository { 58 private val _carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID) 59 override val carrierId = 60 _carrierId 61 .logDiffsForTable( 62 tableLogBuffer, 63 columnPrefix = "", 64 columnName = COL_CARRIER_ID, 65 _carrierId.value, 66 ) 67 .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value) 68 69 private val _isEmergencyOnly = MutableStateFlow(false) 70 override val isEmergencyOnly = 71 _isEmergencyOnly 72 .logDiffsForTable( 73 tableLogBuffer, 74 columnPrefix = "", 75 columnName = COL_EMERGENCY, 76 _isEmergencyOnly.value 77 ) 78 .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value) 79 80 private val _isRoaming = MutableStateFlow(false) 81 override val isRoaming = 82 _isRoaming 83 .logDiffsForTable( 84 tableLogBuffer, 85 columnPrefix = "", 86 columnName = COL_ROAMING, 87 _isRoaming.value 88 ) 89 .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value) 90 91 private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null) 92 override val operatorAlphaShort = 93 _operatorAlphaShort 94 .logDiffsForTable( 95 tableLogBuffer, 96 columnPrefix = "", 97 columnName = COL_OPERATOR, 98 _operatorAlphaShort.value 99 ) 100 .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value) 101 102 private val _isInService = MutableStateFlow(false) 103 override val isInService = 104 _isInService 105 .logDiffsForTable( 106 tableLogBuffer, 107 columnPrefix = "", 108 columnName = COL_IS_IN_SERVICE, 109 _isInService.value 110 ) 111 .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value) 112 113 private val _isGsm = MutableStateFlow(false) 114 override val isGsm = 115 _isGsm 116 .logDiffsForTable( 117 tableLogBuffer, 118 columnPrefix = "", 119 columnName = COL_IS_GSM, 120 _isGsm.value 121 ) 122 .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value) 123 124 private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) 125 override val cdmaLevel = 126 _cdmaLevel 127 .logDiffsForTable( 128 tableLogBuffer, 129 columnPrefix = "", 130 columnName = COL_CDMA_LEVEL, 131 _cdmaLevel.value 132 ) 133 .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value) 134 135 private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) 136 override val primaryLevel = 137 _primaryLevel 138 .logDiffsForTable( 139 tableLogBuffer, 140 columnPrefix = "", 141 columnName = COL_PRIMARY_LEVEL, 142 _primaryLevel.value 143 ) 144 .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value) 145 146 private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected) 147 override val dataConnectionState = 148 _dataConnectionState 149 .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value) 150 .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value) 151 152 private val _dataActivityDirection = 153 MutableStateFlow( 154 DataActivityModel( 155 hasActivityIn = false, 156 hasActivityOut = false, 157 ) 158 ) 159 override val dataActivityDirection = 160 _dataActivityDirection 161 .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value) 162 .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value) 163 164 private val _carrierNetworkChangeActive = MutableStateFlow(false) 165 override val carrierNetworkChangeActive = 166 _carrierNetworkChangeActive 167 .logDiffsForTable( 168 tableLogBuffer, 169 columnPrefix = "", 170 columnName = COL_CARRIER_NETWORK_CHANGE, 171 _carrierNetworkChangeActive.value 172 ) 173 .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value) 174 175 private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> = 176 MutableStateFlow(ResolvedNetworkType.UnknownNetworkType) 177 override val resolvedNetworkType = 178 _resolvedNetworkType 179 .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value) 180 .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value) 181 182 override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS) 183 184 override val dataEnabled = MutableStateFlow(true) 185 186 override val cdmaRoaming = MutableStateFlow(false) 187 188 override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived(DEMO_CARRIER_NAME)) 189 190 override val carrierName = 191 MutableStateFlow(NetworkNameModel.SubscriptionDerived(DEMO_CARRIER_NAME)) 192 193 override val isAllowedDuringAirplaneMode = MutableStateFlow(false) 194 195 /** 196 * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately 197 * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level 198 * repository. 199 */ 200 fun processDemoMobileEvent( 201 event: FakeNetworkEventModel.Mobile, 202 resolvedNetworkType: ResolvedNetworkType, 203 ) { 204 // This is always true here, because we split out disabled states at the data-source level 205 dataEnabled.value = true 206 networkName.value = NetworkNameModel.IntentDerived(event.name) 207 carrierName.value = NetworkNameModel.SubscriptionDerived("${event.name} ${event.subId}") 208 209 _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID 210 211 numberOfLevels.value = 212 if (event.inflateStrength) DEFAULT_NUM_LEVELS + 1 else DEFAULT_NUM_LEVELS 213 214 cdmaRoaming.value = event.roaming 215 _isRoaming.value = event.roaming 216 // TODO(b/261029387): not yet supported 217 _isEmergencyOnly.value = false 218 _operatorAlphaShort.value = event.name 219 _isInService.value = (event.level ?: 0) > 0 220 // TODO(b/261029387): not yet supported 221 _isGsm.value = false 222 _cdmaLevel.value = event.level ?: 0 223 _primaryLevel.value = event.level ?: 0 224 // TODO(b/261029387): not yet supported 225 _dataConnectionState.value = DataConnectionState.Connected 226 _dataActivityDirection.value = 227 (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel() 228 _carrierNetworkChangeActive.value = event.carrierNetworkChange 229 _resolvedNetworkType.value = resolvedNetworkType 230 231 isAllowedDuringAirplaneMode.value = false 232 } 233 234 fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) { 235 // This is always true here, because we split out disabled states at the data-source level 236 dataEnabled.value = true 237 networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME) 238 carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME) 239 // TODO(b/276943904): is carrierId a thing with carrier merged networks? 240 _carrierId.value = INVALID_SUBSCRIPTION_ID 241 numberOfLevels.value = event.numberOfLevels 242 cdmaRoaming.value = false 243 _primaryLevel.value = event.level 244 _cdmaLevel.value = event.level 245 _dataActivityDirection.value = event.activity.toMobileDataActivityModel() 246 247 // These fields are always the same for carrier-merged networks 248 _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType 249 _dataConnectionState.value = DataConnectionState.Connected 250 _isRoaming.value = false 251 _isEmergencyOnly.value = false 252 _operatorAlphaShort.value = null 253 _isInService.value = true 254 _isGsm.value = false 255 _carrierNetworkChangeActive.value = false 256 isAllowedDuringAirplaneMode.value = true 257 } 258 259 companion object { 260 private const val DEMO_CARRIER_NAME = "Demo Carrier" 261 private const val CARRIER_MERGED_NAME = "Carrier Merged Network" 262 } 263 } 264