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
27 namespace OHOS {
28 namespace Telephony {
DataConnectionMonitor(const std::shared_ptr<AppExecFwk::EventRunner> & runner,int32_t slotId)29 DataConnectionMonitor::DataConnectionMonitor(const std::shared_ptr<AppExecFwk::EventRunner> &runner, int32_t slotId)
30 : AppExecFwk::EventHandler(runner), slotId_(slotId)
31 {
32 trafficManager_ = std::make_unique<TrafficManagement>();
33 stallDetectionTrafficManager_ = std::make_unique<TrafficManagement>();
34 if (trafficManager_ == nullptr || stallDetectionTrafficManager_ == nullptr) {
35 TELEPHONY_LOGE("TrafficManager or stallDetectionTrafficManager init failed");
36 }
37 }
38
StartStallDetectionTimer()39 void DataConnectionMonitor::StartStallDetectionTimer()
40 {
41 TELEPHONY_LOGI("Slot%{public}d: start stall detection", slotId_);
42 stallDetectionEnabled = true;
43 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled) {
44 AppExecFwk::InnerEvent::Pointer event =
45 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
46 SendEvent(event, DEFAULT_STALL_DETECTION_PERIOD, Priority::LOW);
47 }
48 }
49
OnStallDetectionTimer()50 void DataConnectionMonitor::OnStallDetectionTimer()
51 {
52 TELEPHONY_LOGI("Slot%{public}d: on stall detection", slotId_);
53 UpdateFlowInfo();
54 if (noRecvPackets_ > RECOVERY_TRIGGER_PACKET) {
55 HandleRecovery();
56 noRecvPackets_ = 0;
57 }
58 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled) {
59 AppExecFwk::InnerEvent::Pointer event =
60 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
61 SendEvent(event, DEFAULT_STALL_DETECTION_PERIOD, Priority::LOW);
62 }
63 }
64
StopStallDetectionTimer()65 void DataConnectionMonitor::StopStallDetectionTimer()
66 {
67 TELEPHONY_LOGI("Slot%{public}d: stop stall detection", slotId_);
68 stallDetectionEnabled = false;
69 RemoveEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
70 }
71
UpdateFlowInfo()72 void DataConnectionMonitor::UpdateFlowInfo()
73 {
74 if (stallDetectionTrafficManager_ == nullptr) {
75 TELEPHONY_LOGE("Slot%{public}d: stallDetectionTrafficManager_ is null", slotId_);
76 return;
77 }
78 int64_t previousSentPackets = 0;
79 int64_t previousRecvPackets = 0;
80 int64_t currentSentPackets = 0;
81 int64_t currentRecvPackets = 0;
82 stallDetectionTrafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
83 stallDetectionTrafficManager_->UpdatePacketData();
84 stallDetectionTrafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
85 int64_t sentPackets = currentSentPackets - previousSentPackets;
86 int64_t recvPackets = currentRecvPackets - previousRecvPackets;
87 if (sentPackets > 0 && recvPackets == 0) {
88 noRecvPackets_ += sentPackets;
89 } else if ((sentPackets > 0 && recvPackets > 0) || (sentPackets == 0 && recvPackets > 0)) {
90 noRecvPackets_ = 0;
91 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
92 } else {
93 TELEPHONY_LOGE("Slot%{public}d: Update Flow Info nothing to do", slotId_);
94 }
95 }
96
HandleRecovery()97 void DataConnectionMonitor::HandleRecovery()
98 {
99 switch (dataRecoveryState_) {
100 case RecoveryState::STATE_REQUEST_CONTEXT_LIST: {
101 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: get data call list", slotId_);
102 dataRecoveryState_ = RecoveryState::STATE_CLEANUP_CONNECTIONS;
103 GetPdpContextList();
104 CellularDataHiSysEvent::WriteDataDeactiveBehaviorEvent(slotId_, DataDisconnectCause::ON_THE_NETWORK_SIDE);
105 break;
106 }
107 case RecoveryState::STATE_CLEANUP_CONNECTIONS: {
108 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: cleanup connections", slotId_);
109 dataRecoveryState_ = RecoveryState::STATE_REREGISTER_NETWORK;
110 int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections(
111 slotId_, DisConnectionReason::REASON_RETRY_CONNECTION);
112 if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) {
113 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: cleanup connections failed", slotId_);
114 }
115 break;
116 }
117 case RecoveryState::STATE_REREGISTER_NETWORK: {
118 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: re-register network", slotId_);
119 dataRecoveryState_ = RecoveryState::STATE_RADIO_STATUS_RESTART;
120 GetPreferredNetworkPara();
121 break;
122 }
123 case RecoveryState::STATE_RADIO_STATUS_RESTART: {
124 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: radio restart", slotId_);
125 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
126 int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections(
127 slotId_, DisConnectionReason::REASON_RETRY_CONNECTION);
128 if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) {
129 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: radio restart cleanup connections failed", slotId_);
130 }
131 SetRadioState(CORE_SERVICE_POWER_OFF, RadioEvent::RADIO_OFF);
132 break;
133 }
134 default: {
135 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery is falsie", slotId_);
136 break;
137 }
138 }
139 }
140
BeginNetStatistics()141 void DataConnectionMonitor::BeginNetStatistics()
142 {
143 updateNetStat_ = true;
144 UpdateNetTrafficState();
145 }
146
EndNetStatistics()147 void DataConnectionMonitor::EndNetStatistics()
148 {
149 RemoveEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK);
150 updateNetStat_ = false;
151 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
152 }
153
UpdateNetTrafficState()154 void DataConnectionMonitor::UpdateNetTrafficState()
155 {
156 if (!HasInnerEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK) && updateNetStat_) {
157 UpdateDataFlowType();
158 AppExecFwk::InnerEvent::Pointer event =
159 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_RUN_MONITOR_TASK);
160 SendEvent(event, DEFAULT_NET_STATISTICS_PERIOD);
161 }
162 }
163
GetPdpContextList()164 void DataConnectionMonitor::GetPdpContextList()
165 {
166 CoreManagerInner::GetInstance().GetPdpContextList(slotId_,
167 RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, shared_from_this());
168 }
169
SetRadioState(const int32_t & radioState,const int32_t & eventCode)170 void DataConnectionMonitor::SetRadioState(const int32_t &radioState, const int32_t &eventCode)
171 {
172 CoreManagerInner::GetInstance().SetRadioState(slotId_, eventCode, radioState, 0, shared_from_this());
173 }
174
GetPreferredNetworkPara()175 void DataConnectionMonitor::GetPreferredNetworkPara()
176 {
177 CoreManagerInner::GetInstance().GetPreferredNetworkPara(slotId_,
178 RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE, shared_from_this());
179 }
180
SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer & event)181 void DataConnectionMonitor::SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer &event)
182 {
183 std::shared_ptr<PreferredNetworkTypeInfo> preferredNetworkInfo = event->GetSharedObject<PreferredNetworkTypeInfo>();
184 if (preferredNetworkInfo == nullptr) {
185 TELEPHONY_LOGE("preferredNetworkInfo is null");
186 return;
187 }
188 int32_t networkType = preferredNetworkInfo->preferredNetworkType;
189 CoreManagerInner::GetInstance().SetPreferredNetworkPara(slotId_,
190 RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE, networkType, shared_from_this());
191 }
192
UpdateDataFlowType()193 void DataConnectionMonitor::UpdateDataFlowType()
194 {
195 if (trafficManager_ == nullptr) {
196 TELEPHONY_LOGE("Slot%{public}d: trafficManager is null", slotId_);
197 return;
198 }
199 int64_t previousSentPackets = 0;
200 int64_t previousRecvPackets = 0;
201 int64_t currentSentPackets = 0;
202 int64_t currentRecvPackets = 0;
203 trafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
204 trafficManager_->UpdatePacketData();
205 trafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
206 int64_t sentPackets = currentSentPackets - previousSentPackets;
207 int64_t recvPackets = currentRecvPackets - previousRecvPackets;
208 CellDataFlowType previousDataFlowType = dataFlowType_;
209 if (previousSentPackets != 0 || previousRecvPackets != 0) {
210 if (sentPackets > 0 && recvPackets == 0) {
211 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP;
212 } else if (sentPackets == 0 && recvPackets > 0) {
213 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_DOWN;
214 } else if (sentPackets > 0 && recvPackets > 0) {
215 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP_DOWN;
216 } else {
217 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
218 }
219 }
220 if (previousDataFlowType != dataFlowType_) {
221 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
222 }
223 }
224
GetDataFlowType()225 CellDataFlowType DataConnectionMonitor::GetDataFlowType()
226 {
227 return dataFlowType_;
228 }
229
SetDataFlowType(CellDataFlowType dataFlowType)230 void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType)
231 {
232 if (dataFlowType_ != dataFlowType) {
233 dataFlowType_ = dataFlowType;
234 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
235 }
236 }
237
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)238 void DataConnectionMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
239 {
240 if (event == nullptr) {
241 TELEPHONY_LOGE("Slot%{public}d: event is null", slotId_);
242 return;
243 }
244 uint32_t eventID = event->GetInnerEventId();
245 switch (eventID) {
246 case CellularDataEventCode::MSG_RUN_MONITOR_TASK: {
247 UpdateNetTrafficState();
248 break;
249 }
250 case CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID:
251 OnStallDetectionTimer();
252 break;
253 case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED:
254 TELEPHONY_LOGI("Slot%{public}d: radio call list changed complete", slotId_);
255 break;
256 case RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE:
257 SetPreferredNetworkPara(event);
258 break;
259 case RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE:
260 TELEPHONY_LOGI("Slot%{public}d: set preferred network mode complete", slotId_);
261 break;
262 case RadioEvent::RADIO_OFF:
263 SetRadioState(CORE_SERVICE_POWER_ON, RadioEvent::RADIO_ON);
264 break;
265 case RadioEvent::RADIO_ON:
266 TELEPHONY_LOGI("Slot%{public}d: set radio state on complete", slotId_);
267 break;
268 default:
269 TELEPHONY_LOGI("Slot%{public}d: connection monitor ProcessEvent code = %{public}u", slotId_, eventID);
270 break;
271 }
272 }
273 } // namespace Telephony
274 } // namespace OHOS
275