• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>(slotId);
33     stallDetectionTrafficManager_ = std::make_unique<TrafficManagement>(slotId);
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     if (dataFlowType_ != CellDataFlowType::DATA_FLOW_TYPE_NONE) {
152         dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
153         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
154     }
155 }
156 
UpdateNetTrafficState()157 void DataConnectionMonitor::UpdateNetTrafficState()
158 {
159     if (!HasInnerEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK) && updateNetStat_) {
160         UpdateDataFlowType();
161         AppExecFwk::InnerEvent::Pointer event =
162             AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_RUN_MONITOR_TASK);
163         SendEvent(event, DEFAULT_NET_STATISTICS_PERIOD);
164     }
165 }
166 
GetPdpContextList()167 void DataConnectionMonitor::GetPdpContextList()
168 {
169     CoreManagerInner::GetInstance().GetPdpContextList(slotId_,
170         RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, shared_from_this());
171 }
172 
SetRadioState(const int32_t & radioState,const int32_t & eventCode)173 void DataConnectionMonitor::SetRadioState(const int32_t &radioState, const int32_t &eventCode)
174 {
175     CoreManagerInner::GetInstance().SetRadioState(slotId_, eventCode, radioState, 0, shared_from_this());
176 }
177 
GetPreferredNetworkPara()178 void DataConnectionMonitor::GetPreferredNetworkPara()
179 {
180     CoreManagerInner::GetInstance().GetPreferredNetworkPara(slotId_,
181         RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE, shared_from_this());
182 }
183 
SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer & event)184 void DataConnectionMonitor::SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer &event)
185 {
186     std::shared_ptr<PreferredNetworkTypeInfo> preferredNetworkInfo = event->GetSharedObject<PreferredNetworkTypeInfo>();
187     if (preferredNetworkInfo == nullptr) {
188         TELEPHONY_LOGE("preferredNetworkInfo is null");
189         return;
190     }
191     int32_t networkType = preferredNetworkInfo->preferredNetworkType;
192     CoreManagerInner::GetInstance().SetPreferredNetworkPara(slotId_,
193         RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE, networkType, shared_from_this());
194 }
195 
UpdateDataFlowType()196 void DataConnectionMonitor::UpdateDataFlowType()
197 {
198     if (trafficManager_ == nullptr) {
199         TELEPHONY_LOGE("Slot%{public}d: trafficManager is null", slotId_);
200         return;
201     }
202     int64_t previousSentPackets = 0;
203     int64_t previousRecvPackets = 0;
204     int64_t currentSentPackets = 0;
205     int64_t currentRecvPackets = 0;
206     trafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
207     trafficManager_->UpdatePacketData();
208     trafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
209     int64_t sentPackets = currentSentPackets - previousSentPackets;
210     int64_t recvPackets = currentRecvPackets - previousRecvPackets;
211     CellDataFlowType previousDataFlowType = dataFlowType_;
212     if (previousSentPackets != 0 || previousRecvPackets != 0) {
213         if (sentPackets > 0 && recvPackets == 0) {
214             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP;
215         } else if (sentPackets == 0 && recvPackets > 0) {
216             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_DOWN;
217         } else if (sentPackets > 0 && recvPackets > 0) {
218             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP_DOWN;
219         } else {
220             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
221         }
222     }
223     if (previousDataFlowType != dataFlowType_) {
224         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
225     }
226 }
227 
GetDataFlowType()228 CellDataFlowType DataConnectionMonitor::GetDataFlowType()
229 {
230     return dataFlowType_;
231 }
232 
SetDataFlowType(CellDataFlowType dataFlowType)233 void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType)
234 {
235     if (dataFlowType_ != dataFlowType) {
236         dataFlowType_ = dataFlowType;
237         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
238     }
239 }
240 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)241 void DataConnectionMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
242 {
243     if (event == nullptr) {
244         TELEPHONY_LOGE("Slot%{public}d: event is null", slotId_);
245         return;
246     }
247     uint32_t eventID = event->GetInnerEventId();
248     switch (eventID) {
249         case CellularDataEventCode::MSG_RUN_MONITOR_TASK: {
250             UpdateNetTrafficState();
251             break;
252         }
253         case CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID:
254             OnStallDetectionTimer();
255             break;
256         case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED:
257             TELEPHONY_LOGI("Slot%{public}d: radio call list changed complete", slotId_);
258             break;
259         case RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE:
260             SetPreferredNetworkPara(event);
261             break;
262         case RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE:
263             TELEPHONY_LOGI("Slot%{public}d: set preferred network mode complete", slotId_);
264             break;
265         case RadioEvent::RADIO_OFF:
266             SetRadioState(CORE_SERVICE_POWER_ON, RadioEvent::RADIO_ON);
267             break;
268         case RadioEvent::RADIO_ON:
269             TELEPHONY_LOGI("Slot%{public}d: set radio state on complete", slotId_);
270             break;
271         default:
272             TELEPHONY_LOGI("Slot%{public}d: connection monitor ProcessEvent code = %{public}u", slotId_, eventID);
273             break;
274     }
275 }
276 } // namespace Telephony
277 } // namespace OHOS
278