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_service.h"
24 #include "cellular_data_types.h"
25
26 namespace OHOS {
27 namespace Telephony {
DataConnectionMonitor(const std::shared_ptr<AppExecFwk::EventRunner> & runner,int32_t slotId)28 DataConnectionMonitor::DataConnectionMonitor(const std::shared_ptr<AppExecFwk::EventRunner> &runner, int32_t slotId)
29 : AppExecFwk::EventHandler(runner), slotId_(slotId)
30 {
31 trafficManager_ = std::make_unique<TrafficManagement>();
32 stallDetectionTrafficManager_ = std::make_unique<TrafficManagement>();
33 }
34
~DataConnectionMonitor()35 DataConnectionMonitor::~DataConnectionMonitor()
36 {
37 RemoveAllEvents();
38 }
39
StartStallDetectionTimer()40 void DataConnectionMonitor::StartStallDetectionTimer()
41 {
42 TELEPHONY_LOGI("Slot%{public}d: start stall detection", slotId_);
43 stallDetectionEnabled = true;
44 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled) {
45 AppExecFwk::InnerEvent::Pointer event =
46 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
47 SendEvent(event, DEFAULT_STALL_DETECTION_PERIOD, Priority::LOW);
48 }
49 }
50
OnStallDetectionTimer()51 void DataConnectionMonitor::OnStallDetectionTimer()
52 {
53 TELEPHONY_LOGI("Slot%{public}d: on stall detection", slotId_);
54 UpdateFlowInfo();
55 if (noRecvPackets_ > RECOVERY_TRIGGER_PACKET) {
56 HandleRecovery();
57 noRecvPackets_ = 0;
58 }
59 if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled) {
60 AppExecFwk::InnerEvent::Pointer event =
61 AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
62 SendEvent(event, DEFAULT_STALL_DETECTION_PERIOD, Priority::LOW);
63 }
64 }
65
StopStallDetectionTimer()66 void DataConnectionMonitor::StopStallDetectionTimer()
67 {
68 TELEPHONY_LOGI("Slot%{public}d: stop stall detection", slotId_);
69 stallDetectionEnabled = false;
70 RemoveEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
71 }
72
UpdateFlowInfo()73 void DataConnectionMonitor::UpdateFlowInfo()
74 {
75 if (stallDetectionTrafficManager_ == nullptr) {
76 TELEPHONY_LOGE("Slot%{public}d: stallDetectionTrafficManager_ is null", slotId_);
77 return;
78 }
79 int64_t previousSentPackets = 0;
80 int64_t previousRecvPackets = 0;
81 int64_t currentSentPackets = 0;
82 int64_t currentRecvPackets = 0;
83 stallDetectionTrafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
84 stallDetectionTrafficManager_->UpdatePacketData();
85 stallDetectionTrafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
86 int64_t sentPackets = currentSentPackets - previousSentPackets;
87 int64_t recvPackets = currentRecvPackets - previousRecvPackets;
88 if (sentPackets > 0 && recvPackets == 0) {
89 noRecvPackets_ += sentPackets;
90 } else if ((sentPackets > 0 && recvPackets > 0) || (sentPackets == 0 && recvPackets > 0)) {
91 noRecvPackets_ = 0;
92 dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
93 } else {
94 TELEPHONY_LOGE("Slot%{public}d: Update Flow Info nothing to do", slotId_);
95 }
96 }
97
HandleRecovery()98 void DataConnectionMonitor::HandleRecovery()
99 {
100 switch (dataRecoveryState_) {
101 case RecoveryState::STATE_REQUEST_CONTEXT_LIST: {
102 TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: get data call list", slotId_);
103 dataRecoveryState_ = RecoveryState::STATE_CLEANUP_CONNECTIONS;
104 GetPdpContextList();
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 int32_t networkType = preferredNetworkInfo->preferredNetworkType;
185 CoreManagerInner::GetInstance().SetPreferredNetworkPara(slotId_,
186 RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE, networkType, shared_from_this());
187 }
188
UpdateDataFlowType()189 void DataConnectionMonitor::UpdateDataFlowType()
190 {
191 if (trafficManager_ == nullptr) {
192 TELEPHONY_LOGE("Slot%{public}d: trafficManager is null", slotId_);
193 return;
194 }
195 int64_t previousSentPackets = 0;
196 int64_t previousRecvPackets = 0;
197 int64_t currentSentPackets = 0;
198 int64_t currentRecvPackets = 0;
199 trafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
200 trafficManager_->UpdatePacketData();
201 trafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
202 int64_t sentPackets = currentSentPackets - previousSentPackets;
203 int64_t recvPackets = currentRecvPackets - previousRecvPackets;
204 CellDataFlowType previousDataFlowType = dataFlowType_;
205 if (previousSentPackets != 0 || previousRecvPackets != 0) {
206 if (sentPackets > 0 && recvPackets == 0) {
207 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP;
208 } else if (sentPackets == 0 && recvPackets > 0) {
209 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_DOWN;
210 } else if (sentPackets > 0 && recvPackets > 0) {
211 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP_DOWN;
212 } else {
213 dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
214 }
215 }
216 if (previousDataFlowType != dataFlowType_) {
217 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
218 }
219 }
220
GetDataFlowType()221 CellDataFlowType DataConnectionMonitor::GetDataFlowType()
222 {
223 return dataFlowType_;
224 }
225
SetDataFlowType(CellDataFlowType dataFlowType)226 void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType)
227 {
228 if (dataFlowType_ != dataFlowType) {
229 dataFlowType_ = dataFlowType;
230 StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
231 }
232 }
233
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)234 void DataConnectionMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
235 {
236 if (event == nullptr) {
237 TELEPHONY_LOGE("Slot%{public}d: event is null", slotId_);
238 return;
239 }
240 uint32_t eventID = event->GetInnerEventId();
241 switch (eventID) {
242 case CellularDataEventCode::MSG_RUN_MONITOR_TASK: {
243 UpdateNetTrafficState();
244 break;
245 }
246 case CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID:
247 OnStallDetectionTimer();
248 break;
249 case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED:
250 TELEPHONY_LOGI("Slot%{public}d: radio call list changed complete", slotId_);
251 break;
252 case RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE:
253 SetPreferredNetworkPara(event);
254 break;
255 case RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE:
256 TELEPHONY_LOGI("Slot%{public}d: set preferred network mode complete", slotId_);
257 break;
258 case RadioEvent::RADIO_OFF:
259 SetRadioState(CORE_SERVICE_POWER_ON, RadioEvent::RADIO_ON);
260 break;
261 case RadioEvent::RADIO_ON:
262 TELEPHONY_LOGI("Slot%{public}d: set radio state on complete", slotId_);
263 break;
264 default:
265 TELEPHONY_LOGI("Slot%{public}d: connection monitor ProcessEvent code = %{public}u", slotId_, eventID);
266 break;
267 }
268 }
269 } // namespace Telephony
270 } // namespace OHOS