• 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>();
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