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