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