• 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 #include "cellular_data_constant.h"
27 #include "data_service_ext_wrapper.h"
28 #include "telephony_ext_wrapper.h"
29 
30 #ifdef ABILITY_POWER_SUPPORT
31 #include "power_mgr_client.h"
32 #endif
33 
34 namespace OHOS {
35 namespace Telephony {
DataConnectionMonitor(int32_t slotId)36 DataConnectionMonitor::DataConnectionMonitor(int32_t slotId) : TelEventHandler("DataConnectionMonitor"), slotId_(slotId)
37 {
38     trafficManager_ = std::make_unique<TrafficManagement>(slotId);
39     stallDetectionTrafficManager_ = std::make_unique<TrafficManagement>(slotId);
40     if (trafficManager_ == nullptr || stallDetectionTrafficManager_ == nullptr) {
41         TELEPHONY_LOGE("TrafficManager or stallDetectionTrafficManager init failed");
42     }
43 }
44 
HandleScreenStateChanged(bool isScreenOn)45 void DataConnectionMonitor::HandleScreenStateChanged(bool isScreenOn)
46 {
47     if (isScreenOn_ == isScreenOn) {
48         return;
49     }
50     isScreenOn_ = isScreenOn;
51     const int32_t defSlotId = CoreManagerInner::GetInstance().GetDefaultCellularDataSlotId();
52     if (slotId_ != defSlotId && !IsVsimEnabled()) {
53         return;
54     }
55     StopStallDetectionTimer();
56     StartStallDetectionTimer();
57 }
58 
IsVsimEnabled()59 bool DataConnectionMonitor::IsVsimEnabled()
60 {
61 #ifdef OHOS_BUILD_ENABLE_TELEPHONY_EXT
62     if (TELEPHONY_EXT_WRAPPER.getVSimSlotId_ && TELEPHONY_EXT_WRAPPER.isVSimEnabled_) {
63         int vSimSlotId = INVALID_SLOT_ID;
64         TELEPHONY_EXT_WRAPPER.getVSimSlotId_(vSimSlotId);
65         if (vSimSlotId == slotId_ && TELEPHONY_EXT_WRAPPER.isVSimEnabled_()) {
66             return true;
67         }
68     }
69 #endif
70     return false;
71 }
72 
IsAggressiveRecovery()73 bool DataConnectionMonitor::IsAggressiveRecovery()
74 {
75     return (dataRecoveryState_ == RecoveryState::STATE_CLEANUP_CONNECTIONS) ||
76         (dataRecoveryState_ == RecoveryState::STATE_REREGISTER_NETWORK) ||
77         (dataRecoveryState_ == RecoveryState::STATE_RADIO_STATUS_RESTART);
78 }
79 
GetStallDetectionPeriod()80 int32_t DataConnectionMonitor::GetStallDetectionPeriod()
81 {
82     if (isScreenOn_ || IsAggressiveRecovery()) {
83         return DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT;
84     }
85     return DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT;
86 }
87 
StartStallDetectionTimer()88 void DataConnectionMonitor::StartStallDetectionTimer()
89 {
90     TELEPHONY_LOGI("Slot%{public}d: start stall detection", slotId_);
91     stallDetectionEnabled_ = true;
92     int32_t stallDetectionPeriod = GetStallDetectionPeriod();
93     TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod);
94     if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID)) {
95         AppExecFwk::InnerEvent::Pointer event =
96             AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
97         SendEvent(event, stallDetectionPeriod, Priority::LOW);
98     }
99 }
100 
OnStallDetectionTimer()101 __attribute__((no_sanitize("cfi"))) void DataConnectionMonitor::OnStallDetectionTimer()
102 {
103     TELEPHONY_LOGD("Slot%{public}d: on stall detection", slotId_);
104 #ifdef OHOS_BUILD_ENABLE_DATA_SERVICE_EXT
105     if (DATA_SERVICE_EXT_WRAPPER.requestTcpAndDnsPackets_) {
106         DATA_SERVICE_EXT_WRAPPER.requestTcpAndDnsPackets_();
107         return;
108     }
109 #endif
110     UpdateFlowInfo();
111     if (noRecvPackets_ > RECOVERY_TRIGGER_PACKET) {
112         HandleRecovery();
113         noRecvPackets_ = 0;
114     }
115     int32_t stallDetectionPeriod = GetStallDetectionPeriod();
116     TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod);
117     if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled_) {
118         AppExecFwk::InnerEvent::Pointer event =
119             AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
120         SendEvent(event, stallDetectionPeriod, Priority::LOW);
121     }
122 }
123 
StopStallDetectionTimer()124 void DataConnectionMonitor::StopStallDetectionTimer()
125 {
126     TELEPHONY_LOGD("Slot%{public}d: stop stall detection", slotId_);
127     stallDetectionEnabled_ = false;
128     RemoveEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
129 }
130 
UpdateFlowInfo()131 void DataConnectionMonitor::UpdateFlowInfo()
132 {
133     if (stallDetectionTrafficManager_ == nullptr) {
134         TELEPHONY_LOGE("Slot%{public}d: stallDetectionTrafficManager_ is null", slotId_);
135         return;
136     }
137     int64_t previousSentPackets = 0;
138     int64_t previousRecvPackets = 0;
139     int64_t currentSentPackets = 0;
140     int64_t currentRecvPackets = 0;
141     stallDetectionTrafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
142     stallDetectionTrafficManager_->UpdatePacketData();
143     stallDetectionTrafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
144     int64_t sentPackets = currentSentPackets - previousSentPackets;
145     int64_t recvPackets = currentRecvPackets - previousRecvPackets;
146     if (sentPackets > 0 && recvPackets == 0) {
147         noRecvPackets_ += sentPackets;
148     } else if ((sentPackets > 0 && recvPackets > 0) || (sentPackets == 0 && recvPackets > 0)) {
149         noRecvPackets_ = 0;
150         dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
151     } else {
152         TELEPHONY_LOGD("Slot%{public}d: Update Flow Info nothing to do", slotId_);
153     }
154 }
155 
HandleRecovery()156 void DataConnectionMonitor::HandleRecovery()
157 {
158     if (callState_ != static_cast<int32_t>(TelCallStatus::CALL_STATUS_IDLE) &&
159         callState_ != static_cast<int32_t>(TelCallStatus::CALL_STATUS_DISCONNECTED)) {
160         TELEPHONY_LOGI("Slot%{public}d: Stop recovery while call is busy", slotId_);
161         dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
162         return;
163     }
164     switch (dataRecoveryState_) {
165         case RecoveryState::STATE_REQUEST_CONTEXT_LIST: {
166             TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: get data call list", slotId_);
167             dataRecoveryState_ = RecoveryState::STATE_CLEANUP_CONNECTIONS;
168             GetPdpContextList();
169             CellularDataHiSysEvent::WriteDataDeactiveBehaviorEvent(slotId_, DataDisconnectCause::ON_THE_NETWORK_SIDE);
170             break;
171         }
172         case RecoveryState::STATE_CLEANUP_CONNECTIONS: {
173             TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: cleanup connections", slotId_);
174             dataRecoveryState_ = RecoveryState::STATE_REREGISTER_NETWORK;
175             int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections(
176                 slotId_, (int32_t) DisConnectionReason::REASON_RETRY_CONNECTION);
177             if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) {
178                 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: cleanup connections failed", slotId_);
179             }
180             break;
181         }
182         case RecoveryState::STATE_REREGISTER_NETWORK: {
183             TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: re-register network", slotId_);
184             dataRecoveryState_ = RecoveryState::STATE_RADIO_STATUS_RESTART;
185             GetPreferredNetworkPara();
186             break;
187         }
188         case RecoveryState::STATE_RADIO_STATUS_RESTART: {
189             TELEPHONY_LOGI("Slot%{public}d: Handle Recovery: radio restart", slotId_);
190             dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
191             int32_t ret = DelayedRefSingleton<CellularDataService>::GetInstance().ClearAllConnections(
192                 slotId_, (int32_t)DisConnectionReason::REASON_RETRY_CONNECTION);
193             if (ret != static_cast<int32_t>(RequestNetCode::REQUEST_SUCCESS)) {
194                 TELEPHONY_LOGE("Slot%{public}d: Handle Recovery: radio restart cleanup connections failed", slotId_);
195             }
196             SetRadioState(CORE_SERVICE_POWER_OFF, RadioEvent::RADIO_OFF);
197             break;
198         }
199         default: {
200             TELEPHONY_LOGE("Slot%{public}d: Handle Recovery is falsie", slotId_);
201             break;
202         }
203     }
204 }
205 
BeginNetStatistics()206 void DataConnectionMonitor::BeginNetStatistics()
207 {
208     updateNetStat_ = true;
209     UpdateNetTrafficState();
210 }
211 
UpdateCallState(int32_t state)212 void DataConnectionMonitor::UpdateCallState(int32_t state)
213 {
214     callState_ = state;
215 }
216 
EndNetStatistics()217 void DataConnectionMonitor::EndNetStatistics()
218 {
219     RemoveEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK);
220     updateNetStat_ = false;
221     if (dataFlowType_ != CellDataFlowType::DATA_FLOW_TYPE_NONE) {
222         dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
223         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
224     }
225 }
226 
UpdateNetTrafficState()227 void DataConnectionMonitor::UpdateNetTrafficState()
228 {
229     if (!HasInnerEvent(CellularDataEventCode::MSG_RUN_MONITOR_TASK) && updateNetStat_) {
230         UpdateDataFlowType();
231         AppExecFwk::InnerEvent::Pointer event =
232             AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_RUN_MONITOR_TASK);
233         SendEvent(event, DEFAULT_NET_STATISTICS_PERIOD);
234     }
235 }
236 
GetPdpContextList()237 void DataConnectionMonitor::GetPdpContextList()
238 {
239     CoreManagerInner::GetInstance().GetPdpContextList(slotId_,
240         RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, shared_from_this());
241 }
242 
SetRadioState(const int32_t & radioState,const int32_t & eventCode)243 void DataConnectionMonitor::SetRadioState(const int32_t &radioState, const int32_t &eventCode)
244 {
245     CoreManagerInner::GetInstance().SetRadioState(slotId_, eventCode, radioState, 0, shared_from_this());
246 }
247 
GetPreferredNetworkPara()248 void DataConnectionMonitor::GetPreferredNetworkPara()
249 {
250     CoreManagerInner::GetInstance().GetPreferredNetworkPara(slotId_,
251         RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE, shared_from_this());
252 }
253 
SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer & event)254 void DataConnectionMonitor::SetPreferredNetworkPara(const AppExecFwk::InnerEvent::Pointer &event)
255 {
256     std::shared_ptr<PreferredNetworkTypeInfo> preferredNetworkInfo = event->GetSharedObject<PreferredNetworkTypeInfo>();
257     if (preferredNetworkInfo == nullptr) {
258         TELEPHONY_LOGE("preferredNetworkInfo is null");
259         return;
260     }
261     int32_t networkType = preferredNetworkInfo->preferredNetworkType;
262     CoreManagerInner::GetInstance().SetPreferredNetworkPara(slotId_,
263         RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE, networkType, shared_from_this());
264 }
265 
GetDataRecoveryState()266 RecoveryState DataConnectionMonitor::GetDataRecoveryState()
267 {
268     return dataRecoveryState_;
269 }
270 
UpdateDataFlowType()271 void DataConnectionMonitor::UpdateDataFlowType()
272 {
273     if (trafficManager_ == nullptr) {
274         TELEPHONY_LOGE("Slot%{public}d: trafficManager is null", slotId_);
275         return;
276     }
277     int64_t previousSentPackets = 0;
278     int64_t previousRecvPackets = 0;
279     int64_t currentSentPackets = 0;
280     int64_t currentRecvPackets = 0;
281     trafficManager_->GetPacketData(previousSentPackets, previousRecvPackets);
282     trafficManager_->UpdatePacketData();
283     trafficManager_->GetPacketData(currentSentPackets, currentRecvPackets);
284     int64_t sentPackets = currentSentPackets - previousSentPackets;
285     int64_t recvPackets = currentRecvPackets - previousRecvPackets;
286     CellDataFlowType previousDataFlowType = dataFlowType_;
287     if (previousSentPackets != 0 || previousRecvPackets != 0) {
288         if (sentPackets > 0 && recvPackets == 0) {
289             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP;
290         } else if (sentPackets == 0 && recvPackets > 0) {
291             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_DOWN;
292         } else if (sentPackets > 0 && recvPackets > 0) {
293             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_UP_DOWN;
294         } else {
295             dataFlowType_ = CellDataFlowType::DATA_FLOW_TYPE_NONE;
296         }
297     }
298     if (previousDataFlowType != dataFlowType_) {
299         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
300     }
301 }
302 
GetDataFlowType()303 CellDataFlowType DataConnectionMonitor::GetDataFlowType()
304 {
305     return dataFlowType_;
306 }
307 
SetDataFlowType(CellDataFlowType dataFlowType)308 void DataConnectionMonitor::SetDataFlowType(CellDataFlowType dataFlowType)
309 {
310     if (dataFlowType_ != dataFlowType) {
311         dataFlowType_ = dataFlowType;
312         StateNotification::GetInstance().OnUpDataFlowtype(slotId_, dataFlowType_);
313     }
314 }
315 
IsNeedDoRecovery(bool needDoRecovery)316 void DataConnectionMonitor::IsNeedDoRecovery(bool needDoRecovery)
317 {
318     if (needDoRecovery) {
319         HandleRecovery();
320     } else {
321         dataRecoveryState_ = RecoveryState::STATE_REQUEST_CONTEXT_LIST;
322     }
323     int32_t stallDetectionPeriod = GetStallDetectionPeriod();
324     TELEPHONY_LOGI("stallDetectionPeriod = %{public}d", stallDetectionPeriod);
325     if (!HasInnerEvent(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID) && stallDetectionEnabled_) {
326         AppExecFwk::InnerEvent::Pointer event =
327             AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID);
328         SendEvent(event, stallDetectionPeriod, Priority::LOW);
329     }
330 }
331 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)332 void DataConnectionMonitor::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
333 {
334     if (event == nullptr) {
335         TELEPHONY_LOGE("Slot%{public}d: event is null", slotId_);
336         return;
337     }
338     uint32_t eventID = event->GetInnerEventId();
339     switch (eventID) {
340         case CellularDataEventCode::MSG_RUN_MONITOR_TASK: {
341             UpdateNetTrafficState();
342             break;
343         }
344         case CellularDataEventCode::MSG_STALL_DETECTION_EVENT_ID:
345             OnStallDetectionTimer();
346             break;
347         case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED:
348             TELEPHONY_LOGI("Slot%{public}d: radio call list changed complete", slotId_);
349             break;
350         case RadioEvent::RADIO_GET_PREFERRED_NETWORK_MODE:
351             SetPreferredNetworkPara(event);
352             break;
353         case RadioEvent::RADIO_SET_PREFERRED_NETWORK_MODE:
354             TELEPHONY_LOGI("Slot%{public}d: set preferred network mode complete", slotId_);
355             break;
356         case RadioEvent::RADIO_OFF:
357             SetRadioState(CORE_SERVICE_POWER_ON, RadioEvent::RADIO_ON);
358             break;
359         case RadioEvent::RADIO_ON:
360             TELEPHONY_LOGI("Slot%{public}d: set radio state on complete", slotId_);
361             break;
362         default:
363             TELEPHONY_LOGI("Slot%{public}d: connection monitor ProcessEvent code = %{public}u", slotId_, eventID);
364             break;
365     }
366 }
367 } // namespace Telephony
368 } // namespace OHOS
369