1/* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "data_connection_monitor.h" 17 18#include "core_manager_inner.h" 19#include "radio_event.h" 20#include "telephony_log_wrapper.h" 21 22#include "cellular_data_event_code.h" 23#include "cellular_data_hisysevent.h" 24#include "cellular_data_service.h" 25#include "cellular_data_types.h" 26#include "cellular_data_constant.h" 27#include "data_service_ext_wrapper.h" 28 29#ifdef ABILITY_POWER_SUPPORT 30#include "power_mgr_client.h" 31#endif 32 33namespace OHOS { 34namespace Telephony { 35DataConnectionMonitor::DataConnectionMonitor(int32_t slotId) : TelEventHandler("DataConnectionMonitor"), slotId_(slotId) 36{ 37 trafficManager_ = std::make_unique<TrafficManagement>(slotId); 38 stallDetectionTrafficManager_ = std::make_unique<TrafficManagement>(slotId); 39 if (trafficManager_ == nullptr || stallDetectionTrafficManager_ == nullptr) { 40 TELEPHONY_LOGE("TrafficManager or stallDetectionTrafficManager init failed"); 41 } 42} 43 44void DataConnectionMonitor::HandleScreenStateChanged(bool isScreenOn) 45{ 46 if (isScreenOn_ == isScreenOn) { 47 return; 48 } 49 isScreenOn_ = isScreenOn; 50 StopStallDetectionTimer(); 51 StartStallDetectionTimer(); 52} 53 54bool DataConnectionMonitor::IsAggressiveRecovery() 55{ 56 return (dataRecoveryState_ == RecoveryState::STATE_CLEANUP_CONNECTIONS) || 57 (dataRecoveryState_ == RecoveryState::STATE_REREGISTER_NETWORK) || 58 (dataRecoveryState_ == RecoveryState::STATE_RADIO_STATUS_RESTART); 59} 60 61int32_t DataConnectionMonitor::GetStallDetectionPeriod() 62{ 63 if (isScreenOn_ || IsAggressiveRecovery()) { 64 return DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT; 65 } 66 return DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT; 67} 68 69void DataConnectionMonitor::StartStallDetectionTimer() 70{ 71 TELEPHONY_LOGI("Slot%{public}d: start stall detection", slotId_); 72 stallDetectionEnabled_ = true; 73 int32_t stallDetectionPeriod = GetStallDetectionPeriod(); 74 TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod); 75 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID)) { 76 AppExecFwk::InnerEvent::Pointer event = 77 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID); 78 SendEvent(event, stallDetectionPeriod, Priority::LOW); 79 } 80} 81 82__attribute__((no_sanitize("cfi"))) void DataConnectionMonitor::OnStallDetectionTimer() 83{ 84 TELEPHONY_LOGD("Slot%{public}d: on stall detection", slotId_); 85#ifdef OHOS_BUILD_ENABLE_DATA_SERVICE_EXT 86 if (DATA_SERVICE_EXT_WRAPPER.requestTcpAndDnsPackets_) { 87 DATA_SERVICE_EXT_WRAPPER.requestTcpAndDnsPackets_(); 88 return; 89 } 90#endif 91 UpdateFlowInfo(); 92 if (noRecvPackets_ > RECOVERY_TRIGGER_PACKET) { 93 HandleRecovery(); 94 noRecvPackets_ = 0; 95 } 96 int32_t stallDetectionPeriod = GetStallDetectionPeriod(); 97 TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod); 98 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled_) { 99 AppExecFwk::InnerEvent::Pointer event = 100 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID); 101 SendEvent(event, stallDetectionPeriod, Priority::LOW); 102 } 103} 104 105void DataConnectionMonitor::StopStallDetectionTimer() 106{ 107 TELEPHONY_LOGD("Slot%{public}d: stop stall detection", slotId_); 108 stallDetectionEnabled_ = false; 109 RemoveEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID); 110} 111 112void DataConnectionMonitor::UpdateFlowInfo() 113{ 114 if (stallDetectionTrafficManager_ == nullptr) { 115 TELEPHONY_LOGE("Slot%{public}d: stallDetectionTrafficManager_ is null", slotId_); 116 return; 117 } 118 int64_t previousSentPackets = 0; 119 int64_t previousRecvPackets = 0; 120 int64_t currentSentPackets = 0; 121 int64_t currentRecvPackets = 0; 122 stallDetectionTrafficManager_->GetPacketData(previousSentPackets, previousRecvPackets); 123 stallDetectionTrafficManager_->UpdatePacketData(); 124 stallDetectionTrafficManager_->GetPacketData(currentSentPackets, currentRecvPackets); 125 int64_t sentPackets = currentSentPackets - previousSentPackets; 126 int64_t recvPackets = currentRecvPackets - previousRecvPackets; 127 if (sentPackets > 0 && recvPackets == 0) { 128 noRecvPackets_ += sentPackets; 129 } else if ((sentPackets > 0 && recvPackets > 0) || (sentPackets == 0 && recvPackets > 0)) { 130 noRecvPackets_ = 0; 131 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST; 132 } else { 133 TELEPHONY_LOGD("Slot%{public}d: Update Flow Info nothing to do", slotId_); 134 } 135} 136 137void DataConnectionMonitor::HandleRecovery() 138{ 139 if (callState_ != static_cast<int32_t>(TelCallStatus::CALL_STATUS_IDLE) && 140 callState_ != static_cast<int32_t>(TelCallStatus::CALL_STATUS_DISCONNECTED)) { 141 TELEPHONY_LOGI("Slot%{public}d: Stop recovery while call is busy", slotId_); 142 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST; 143 return; 144 } 145 switch (dataRecoveryState_) { 146 case RecoveryState::STATE_REQUEST_CONTEXT_LIST: { 147 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: get data call list", slotId_); 148 dataRecoveryState_ = RecoveryState::STATE_CLEANUP_CONNECTIONS; 149 GetPdpContextList(); 150 CellularDataHiSysEvent::WriteDataDeactiveBehaviorEvent(slotId_, DataDisconnectCause::ON_THE_NETWORK_SIDE); 151 break; 152 } 153 case RecoveryState::STATE_CLEANUP_CONNECTIONS: { 154 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: cleanup connections", slotId_); 155 dataRecoveryState_ = RecoveryState::STATE_REREGISTER_NETWORK; 156 int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections( 157 slotId_, DisConnectionReason::REASON_RETRY_CONNECTION); 158 if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) { 159 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: cleanup connections failed", slotId_); 160 } 161 break; 162 } 163 case RecoveryState::STATE_REREGISTER_NETWORK: { 164 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: re-register network", slotId_); 165 dataRecoveryState_ = RecoveryState::STATE_RADIO_STATUS_RESTART; 166 GetPreferredNetworkPara(); 167 break; 168 } 169 case RecoveryState::STATE_RADIO_STATUS_RESTART: { 170 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: radio restart", slotId_); 171 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST; 172 int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections( 173 slotId_, DisConnectionReason::REASON_RETRY_CONNECTION); 174 if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) { 175 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: radio restart cleanup connections failed", slotId_); 176 } 177 SetRadioState(CORE_SERVICE_POWER_OFF, RadioEvent::RADIO_OFF); 178 break; 179 } 180 default: { 181 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery is falsie", slotId_); 182 break; 183 } 184 } 185} 186 187void DataConnectionMonitor::BeginNetStatistics() 188{ 189 updateNetStat_ = true; 190 UpdateNetTrafficState(); 191} 192 193void DataConnectionMonitor::UpdateCallState(int32_t state) 194{ 195 callState_ = state; 196} 197 198void DataConnectionMonitor::EndNetStatistics() 199{ 200 RemoveEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK); 201 updateNetStat_ = false; 202 if (dataFlowType_ != CellDataFlowType::DATA_FLOW_TYPE_NONE) { 203 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE; 204 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_); 205 } 206} 207 208void DataConnectionMonitor::UpdateNetTrafficState() 209{ 210 if (!HasInnerEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK) && updateNetStat_) { 211 UpdateDataFlowType(); 212 AppExecFwk::InnerEvent::Pointer event = 213 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_RUN_MONITOR_TASK); 214 SendEvent(event, DEFAULT_NET_STATISTICS_PERIOD); 215 } 216} 217 218void DataConnectionMonitor::GetPdpContextList() 219{ 220 CoreManagerInner::GetInstance().GetPdpContextList(slotId_, 221 RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, shared_from_this()); 222} 223 224void DataConnectionMonitor::SetRadioState(const int32_t &radioState, const int32_t &eventCode) 225{ 226 CoreManagerInner::GetInstance().SetRadioState(slotId_, eventCode, radioState, 0, shared_from_this()); 227} 228 229void DataConnectionMonitor::GetPreferredNetworkPara() 230{ 231 CoreManagerInner::GetInstance().GetPreferredNetworkPara(slotId_, 232 RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE, shared_from_this()); 233} 234 235void DataConnectionMonitor::SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer &event) 236{ 237 std::shared_ptr<PreferredNetworkTypeInfo> preferredNetworkInfo = event->GetSharedObject<PreferredNetworkTypeInfo>(); 238 if (preferredNetworkInfo == nullptr) { 239 TELEPHONY_LOGE("preferredNetworkInfo is null"); 240 return; 241 } 242 int32_t networkType = preferredNetworkInfo->preferredNetworkType; 243 CoreManagerInner::GetInstance().SetPreferredNetworkPara(slotId_, 244 RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE, networkType, shared_from_this()); 245} 246 247RecoveryState DataConnectionMonitor::GetDataRecoveryState() 248{ 249 return dataRecoveryState_; 250} 251 252void DataConnectionMonitor::UpdateDataFlowType() 253{ 254 if (trafficManager_ == nullptr) { 255 TELEPHONY_LOGE("Slot%{public}d: trafficManager is null", slotId_); 256 return; 257 } 258 int64_t previousSentPackets = 0; 259 int64_t previousRecvPackets = 0; 260 int64_t currentSentPackets = 0; 261 int64_t currentRecvPackets = 0; 262 trafficManager_->GetPacketData(previousSentPackets, previousRecvPackets); 263 trafficManager_->UpdatePacketData(); 264 trafficManager_->GetPacketData(currentSentPackets, currentRecvPackets); 265 int64_t sentPackets = currentSentPackets - previousSentPackets; 266 int64_t recvPackets = currentRecvPackets - previousRecvPackets; 267 CellDataFlowType previousDataFlowType = dataFlowType_; 268 if (previousSentPackets != 0 || previousRecvPackets != 0) { 269 if (sentPackets > 0 && recvPackets == 0) { 270 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP; 271 } else if (sentPackets == 0 && recvPackets > 0) { 272 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_DOWN; 273 } else if (sentPackets > 0 && recvPackets > 0) { 274 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP_DOWN; 275 } else { 276 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE; 277 } 278 } 279 if (previousDataFlowType != dataFlowType_) { 280 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_); 281 } 282} 283 284CellDataFlowType DataConnectionMonitor::GetDataFlowType() 285{ 286 return dataFlowType_; 287} 288 289void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType) 290{ 291 if (dataFlowType_ != dataFlowType) { 292 dataFlowType_ = dataFlowType; 293 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_); 294 } 295} 296 297void DataConnectionMonitor::IsNeedDoRecovery(bool needDoRecovery) 298{ 299 if (needDoRecovery) { 300 HandleRecovery(); 301 } else { 302 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST; 303 } 304 int32_t stallDetectionPeriod = GetStallDetectionPeriod(); 305 TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod); 306 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled_) { 307 AppExecFwk::InnerEvent::Pointer event = 308 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID); 309 SendEvent(event, stallDetectionPeriod, Priority::LOW); 310 } 311} 312 313void DataConnectionMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) 314{ 315 if (event == nullptr) { 316 TELEPHONY_LOGE("Slot%{public}d: event is null", slotId_); 317 return; 318 } 319 uint32_t eventID = event->GetInnerEventId(); 320 switch (eventID) { 321 case CellularDataEventCode::MSG_RUN_MONITOR_TASK: { 322 UpdateNetTrafficState(); 323 break; 324 } 325 case CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID: 326 OnStallDetectionTimer(); 327 break; 328 case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED: 329 TELEPHONY_LOGI("Slot%{public}d: radio call list changed complete", slotId_); 330 break; 331 case RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE: 332 SetPreferredNetworkPara(event); 333 break; 334 case RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE: 335 TELEPHONY_LOGI("Slot%{public}d: set preferred network mode complete", slotId_); 336 break; 337 case RadioEvent::RADIO_OFF: 338 SetRadioState(CORE_SERVICE_POWER_ON, RadioEvent::RADIO_ON); 339 break; 340 case RadioEvent::RADIO_ON: 341 TELEPHONY_LOGI("Slot%{public}d: set radio state on complete", slotId_); 342 break; 343 default: 344 TELEPHONY_LOGI("Slot%{public}d: connection monitor ProcessEvent code = %{public}u", slotId_, eventID); 345 break; 346 } 347} 348} // namespace Telephony 349} // namespace OHOS 350