• 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_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