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
33 namespace OHOS {
34 namespace Telephony {
DataConnectionMonitor(int32_t slotId)35 DataConnectionMonitor::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
IsAggressiveRecovery()44 bool DataConnectionMonitor::IsAggressiveRecovery()
45 {
46 return (dataRecoveryState_ == RecoveryState::STATE_CLEANUP_CONNECTIONS) ||
47 (dataRecoveryState_ == RecoveryState::STATE_REREGISTER_NETWORK) ||
48 (dataRecoveryState_ == RecoveryState::STATE_RADIO_STATUS_RESTART);
49 }
50
IsScreenOn()51 bool DataConnectionMonitor::IsScreenOn()
52 {
53 bool isScreenOn = false;
54 #ifdef ABILITY_POWER_SUPPORT
55 isScreenOn = PowerMgr::PowerMgrClient::GetInstance().IsScreenOn();
56 #endif
57 TELEPHONY_LOGI("isScreenOn = %{public}d.", isScreenOn);
58 return isScreenOn;
59 }
60
GetStallDetectionPeriod()61 int32_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
StartStallDetectionTimer()69 void 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
OnStallDetectionTimer()82 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
StopStallDetectionTimer()105 void DataConnectionMonitor::StopStallDetectionTimer()
106 {
107 TELEPHONY_LOGI("Slot%{public}d: stop stall detection", slotId_);
108 stallDetectionEnabled = false;
109 RemoveEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
110 }
111
UpdateFlowInfo()112 void 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
HandleRecovery()137 void 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
BeginNetStatistics()187 void DataConnectionMonitor::BeginNetStatistics()
188 {
189 updateNetStat_ = true;
190 UpdateNetTrafficState();
191 }
192
UpdateCallState(int32_t state)193 void DataConnectionMonitor::UpdateCallState(int32_t state)
194 {
195 callState_ = state;
196 }
197
EndNetStatistics()198 void 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
UpdateNetTrafficState()208 void 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
GetPdpContextList()218 void DataConnectionMonitor::GetPdpContextList()
219 {
220 CoreManagerInner::GetInstance().GetPdpContextList(slotId_,
221 RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, shared_from_this());
222 }
223
SetRadioState(const int32_t & radioState,const int32_t & eventCode)224 void DataConnectionMonitor::SetRadioState(const int32_t &radioState, const int32_t &eventCode)
225 {
226 CoreManagerInner::GetInstance().SetRadioState(slotId_, eventCode, radioState, 0, shared_from_this());
227 }
228
GetPreferredNetworkPara()229 void DataConnectionMonitor::GetPreferredNetworkPara()
230 {
231 CoreManagerInner::GetInstance().GetPreferredNetworkPara(slotId_,
232 RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE, shared_from_this());
233 }
234
SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer & event)235 void 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
GetDataRecoveryState()247 RecoveryState DataConnectionMonitor::GetDataRecoveryState()
248 {
249 return dataRecoveryState_;
250 }
251
UpdateDataFlowType()252 void 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
GetDataFlowType()284 CellDataFlowType DataConnectionMonitor::GetDataFlowType()
285 {
286 return dataFlowType_;
287 }
288
SetDataFlowType(CellDataFlowType dataFlowType)289 void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType)
290 {
291 if (dataFlowType_ != dataFlowType) {
292 dataFlowType_ = dataFlowType;
293 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
294 }
295 }
296
IsNeedDoRecovery(bool needDoRecovery)297 void 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
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)313 void 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