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_manager.h"
17
18#include "cellular_data_event_code.h"
19#include "cellular_data_handler.h"
20#include "cellular_data_state_machine.h"
21#include "cellular_data_utils.h"
22#include "core_manager_inner.h"
23#include "tel_ril_data_parcel.h"
24#include "operator_config_types.h"
25#include "radio_event.h"
26#include "telephony_log_wrapper.h"
27
28namespace OHOS {
29namespace Telephony {
30DataConnectionManager::DataConnectionManager(int32_t slotId) : StateMachine("DataConnectionManager"), slotId_(slotId)
31{
32    connectionMonitor_ = std::make_shared<DataConnectionMonitor>(slotId);
33    if (connectionMonitor_ == nullptr) {
34        TELEPHONY_LOGE("Slot%{public}d: connectionMonitor_ is null", slotId_);
35        return;
36    }
37}
38
39DataConnectionManager::~DataConnectionManager()
40{
41    if (connectionMonitor_ != nullptr) {
42        connectionMonitor_->RemoveAllEvents();
43    }
44}
45
46void DataConnectionManager::Init()
47{
48    ccmDefaultState_ = std::make_unique<CcmDefaultState>(*this, "CcmDefaultState").release();
49    if (ccmDefaultState_ == nullptr) {
50        TELEPHONY_LOGE("Slot%{public}d: ccmDefaultState_ is null", slotId_);
51        return;
52    }
53    StateMachine::SetOriginalState(ccmDefaultState_);
54    StateMachine::Start();
55}
56
57void DataConnectionManager::AddConnectionStateMachine(const std::shared_ptr<CellularDataStateMachine> &stateMachine)
58{
59    std::lock_guard<std::mutex> lock(stateMachineMutex_);
60    if (stateMachine != nullptr) {
61        stateMachines_.push_back(stateMachine);
62    }
63}
64
65void DataConnectionManager::RemoveConnectionStateMachine(const std::shared_ptr<CellularDataStateMachine> &stateMachine)
66{
67    if (stateMachine == nullptr) {
68        TELEPHONY_LOGE("Slot%{public}d: stateMachine is null", slotId_);
69        return;
70    }
71    std::lock_guard<std::mutex> lock(stateMachineMutex_);
72    for (std::vector<std::shared_ptr<CellularDataStateMachine>>::const_iterator iter =
73        stateMachines_.begin(); iter != stateMachines_.end(); iter++) {
74        if (*iter.base() == stateMachine) {
75            stateMachines_.erase(iter);
76            break;
77        }
78    }
79}
80
81std::vector<std::shared_ptr<CellularDataStateMachine>> DataConnectionManager::GetAllConnectionMachine()
82{
83    std::lock_guard<std::mutex> lock(stateMachineMutex_);
84    return stateMachines_;
85}
86
87void DataConnectionManager::AddActiveConnectionByCid(const std::shared_ptr<CellularDataStateMachine> &stateMachine)
88{
89    std::lock_guard<std::mutex> lock(activeConnectionMutex_);
90    if (stateMachine != nullptr) {
91        cidActiveConnectionMap_[stateMachine->GetCid()] = stateMachine;
92    }
93}
94
95std::shared_ptr<CellularDataStateMachine> DataConnectionManager::GetActiveConnectionByCid(int32_t cid)
96{
97    std::lock_guard<std::mutex> lock(activeConnectionMutex_);
98    std::map<int32_t, std::shared_ptr<CellularDataStateMachine>>::const_iterator it = cidActiveConnectionMap_.find(cid);
99    if (it != cidActiveConnectionMap_.end()) {
100        return it->second;
101    }
102    return nullptr;
103}
104
105std::map<int32_t, std::shared_ptr<CellularDataStateMachine>> DataConnectionManager::GetActiveConnection()
106{
107    std::lock_guard<std::mutex> lock(activeConnectionMutex_);
108    return cidActiveConnectionMap_;
109}
110
111bool DataConnectionManager::IsBandwidthSourceModem() const
112{
113    return bandwidthSourceModem_;
114}
115
116bool DataConnectionManager::isNoActiveConnection()
117{
118    std::lock_guard<std::mutex> lock(activeConnectionMutex_);
119    if (cidActiveConnectionMap_.empty()) {
120        return true;
121    }
122    return false;
123}
124
125void DataConnectionManager::RemoveActiveConnectionByCid(int32_t cid)
126{
127    std::lock_guard<std::mutex> lock(activeConnectionMutex_);
128    if (cidActiveConnectionMap_.find(cid) != cidActiveConnectionMap_.end()) {
129        cidActiveConnectionMap_.erase(cid);
130    }
131}
132
133void DataConnectionManager::StartStallDetectionTimer()
134{
135    if (connectionMonitor_ != nullptr) {
136        connectionMonitor_->StartStallDetectionTimer();
137    }
138}
139
140void DataConnectionManager::StopStallDetectionTimer()
141{
142    if (connectionMonitor_ != nullptr) {
143        connectionMonitor_->StopStallDetectionTimer();
144    }
145}
146
147void DataConnectionManager::RegisterRadioObserver()
148{
149    if (stateMachineEventHandler_ == nullptr) {
150        TELEPHONY_LOGE("stateMachineEventHandler_ is nullptr!");
151        return;
152    }
153    CoreManagerInner &coreInner = CoreManagerInner::GetInstance();
154    coreInner.RegisterCoreNotify(slotId_, stateMachineEventHandler_, RadioEvent::RADIO_CONNECTED, nullptr);
155    coreInner.RegisterCoreNotify(slotId_, stateMachineEventHandler_, RadioEvent::RADIO_DATA_CALL_LIST_CHANGED, nullptr);
156    coreInner.RegisterCoreNotify(
157        slotId_, stateMachineEventHandler_, RadioEvent::RADIO_LINK_CAPABILITY_CHANGED, nullptr);
158}
159
160void DataConnectionManager::UnRegisterRadioObserver() const
161{
162    if (stateMachineEventHandler_ == nullptr) {
163        TELEPHONY_LOGE("stateMachineEventHandler_ is nullptr!");
164        return;
165    }
166    CoreManagerInner &coreInner = CoreManagerInner::GetInstance();
167    coreInner.UnRegisterCoreNotify(slotId_, stateMachineEventHandler_, RadioEvent::RADIO_CONNECTED);
168    coreInner.UnRegisterCoreNotify(slotId_, stateMachineEventHandler_, RadioEvent::RADIO_DATA_CALL_LIST_CHANGED);
169    coreInner.UnRegisterCoreNotify(slotId_, stateMachineEventHandler_, RadioEvent::RADIO_LINK_CAPABILITY_CHANGED);
170}
171
172void CcmDefaultState::StateBegin()
173{
174    connectManager_.RegisterRadioObserver();
175}
176
177void CcmDefaultState::StateEnd()
178{
179    connectManager_.UnRegisterRadioObserver();
180}
181
182bool CcmDefaultState::StateProcess(const AppExecFwk::InnerEvent::Pointer &event)
183{
184    if (event == nullptr) {
185        TELEPHONY_LOGE("event is null");
186        return false;
187    }
188    int32_t id = event->GetInnerEventId();
189    switch (id) {
190        case RadioEvent::RADIO_CONNECTED:
191            TELEPHONY_LOGI("Radio is connected");
192            break;
193        case RadioEvent::RADIO_DATA_CALL_LIST_CHANGED:
194            RadioDataCallListChanged(event);
195            break;
196        case RadioEvent::RADIO_LINK_CAPABILITY_CHANGED:
197            RadioLinkCapabilityChanged(event);
198            break;
199        default:
200            TELEPHONY_LOGE("handle nothing!");
201            return false;
202    }
203    return true;
204}
205
206void CcmDefaultState::RadioDataCallListChanged(const AppExecFwk::InnerEvent::Pointer &event)
207{
208    std::shared_ptr<DataCallResultList> infos = event->GetSharedObject<DataCallResultList>();
209    if (infos == nullptr) {
210        TELEPHONY_LOGE("setupDataCallResultInfo is null");
211        return;
212    }
213    std::map<int32_t, std::shared_ptr<CellularDataStateMachine>> idActiveConnectionMap =
214        connectManager_.GetActiveConnection();
215    UpdateNetworkInfo(event);
216    for (const std::pair<const int32_t, std::shared_ptr<CellularDataStateMachine>>& it : idActiveConnectionMap) {
217        if (it.second == nullptr) {
218            TELEPHONY_LOGI("The activation item is null(%{public}d)", it.first);
219            continue;
220        }
221        int32_t cid = it.second->GetCid();
222        for (size_t i = 0; i < infos->dcList.size(); ++i) {
223            if (infos->dcList[i].cid == cid && infos->dcList[i].active <= 0) {
224                auto object = std::make_shared<SetupDataCallResultInfo>();
225                object->cid = cid;
226                object->reason = infos->dcList[i].reason;
227                object->retryTime = infos->dcList[i].retryTime;
228                object->retryScene = static_cast<int32_t>(RetryScene::RETRY_SCENE_MODEM_DEACTIVATE);
229                TELEPHONY_LOGI("add to retry (modem dend): cid=%{public}d, cause=%{public}d", cid, object->reason);
230                AppExecFwk::InnerEvent::Pointer event =
231                    AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_SM_LOST_CONNECTION, object);
232                it.second->SendEvent(event);
233                break;
234            }
235        }
236    }
237}
238
239void CcmDefaultState::RadioLinkCapabilityChanged(const AppExecFwk::InnerEvent::Pointer &event)
240{
241    std::shared_ptr<DataLinkCapability> linkCapability = event->GetSharedObject<DataLinkCapability>();
242    if (linkCapability == nullptr) {
243        TELEPHONY_LOGE("linkCapability is null");
244        return;
245    }
246    if (connectManager_.IsBandwidthSourceModem()) {
247        std::map<int32_t, std::shared_ptr<CellularDataStateMachine>> idActiveConnectionMap =
248            connectManager_.GetActiveConnection();
249        for (const std::pair<const int32_t, std::shared_ptr<CellularDataStateMachine>> &it : idActiveConnectionMap) {
250            if (it.second == nullptr) {
251                TELEPHONY_LOGI("The activation item is null(%{public}d)", it.first);
252                continue;
253            }
254            AppExecFwk::InnerEvent::Pointer smEvent =
255                AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_SM_LINK_CAPABILITY_CHANGED, linkCapability);
256            it.second->SendEvent(smEvent);
257        }
258    }
259}
260
261void CcmDefaultState::UpdateNetworkInfo(const AppExecFwk::InnerEvent::Pointer &event)
262{
263    std::shared_ptr<DataCallResultList> infos = event->GetSharedObject<DataCallResultList>();
264    if (infos == nullptr) {
265        TELEPHONY_LOGE("dataCallResultList is null");
266        return;
267    }
268    for (SetupDataCallResultInfo &it : infos->dcList) {
269        std::shared_ptr<CellularDataStateMachine> dataConnect = connectManager_.GetActiveConnectionByCid(it.cid);
270        if (dataConnect == nullptr) {
271            TELEPHONY_LOGE("get active connection by cid is :=  %{public}d flag:=  %{public}d ", it.cid, it.flag);
272            continue;
273        }
274        dataConnect->UpdateNetworkInfoIfInActive(it);
275    }
276}
277
278void DataConnectionManager::BeginNetStatistics()
279{
280    if (connectionMonitor_ != nullptr) {
281        connectionMonitor_->BeginNetStatistics();
282    }
283}
284
285void DataConnectionManager::EndNetStatistics()
286{
287    if (connectionMonitor_ != nullptr) {
288        connectionMonitor_->EndNetStatistics();
289    }
290}
291
292void DataConnectionManager::UpdateCallState(int32_t state)
293{
294    if (connectionMonitor_ != nullptr) {
295        connectionMonitor_->UpdateCallState(state);
296    }
297}
298
299int32_t DataConnectionManager::GetDataRecoveryState()
300{
301    if (connectionMonitor_ != nullptr) {
302        return static_cast<int32_t>(connectionMonitor_->GetDataRecoveryState());
303    }
304    return -1;
305}
306
307int32_t DataConnectionManager::GetSlotId() const
308{
309    return slotId_;
310}
311
312int32_t DataConnectionManager::GetDataFlowType()
313{
314    if (connectionMonitor_ == nullptr) {
315        TELEPHONY_LOGE("Slot%{public}d: connection monitor is null", slotId_);
316        return static_cast<int32_t>(CellDataFlowType::DATA_FLOW_TYPE_NONE);
317    }
318    CellDataFlowType flowType = connectionMonitor_->GetDataFlowType();
319    return static_cast<int32_t>(flowType);
320}
321
322void DataConnectionManager::SetDataFlowType(CellDataFlowType dataFlowType)
323{
324    if (connectionMonitor_ == nullptr) {
325        TELEPHONY_LOGE("Slot%{public}d: connection monitor is null", slotId_);
326        return;
327    }
328    connectionMonitor_->SetDataFlowType(dataFlowType);
329}
330
331void DataConnectionManager::GetDefaultBandWidthsConfig()
332{
333    OperatorConfig operatorConfig;
334    CoreManagerInner::GetInstance().GetOperatorConfigs(slotId_, operatorConfig);
335    if (operatorConfig.boolValue.find(KEY_BANDWIDTH_SOURCE_USE_MODEM_BOOL) != operatorConfig.boolValue.end()) {
336        bandwidthSourceModem_ = operatorConfig.boolValue[KEY_BANDWIDTH_SOURCE_USE_MODEM_BOOL];
337    }
338    if (operatorConfig.boolValue.find(KEY_UPLINK_BANDWIDTH_NR_NSA_USE_LTE_VALUE_BOOL) !=
339        operatorConfig.boolValue.end()) {
340        uplinkUseLte_ = operatorConfig.boolValue[KEY_UPLINK_BANDWIDTH_NR_NSA_USE_LTE_VALUE_BOOL];
341    }
342    std::vector<std::string> linkBandwidthVec;
343    if (operatorConfig.stringArrayValue.find(KEY_BANDWIDTH_STRING_ARRAY) != operatorConfig.stringArrayValue.end()) {
344        linkBandwidthVec = operatorConfig.stringArrayValue[KEY_BANDWIDTH_STRING_ARRAY];
345    }
346    if (linkBandwidthVec.empty()) {
347        linkBandwidthVec = CellularDataUtils::Split(DEFAULT_BANDWIDTH_CONFIG, ";");
348    }
349    std::lock_guard<std::mutex> lock(bandwidthConfigMutex_);
350    bandwidthConfigMap_.clear();
351    for (std::string temp : linkBandwidthVec) {
352        std::vector<std::string> linkBandwidths = CellularDataUtils::Split(temp, ":");
353        if (linkBandwidths.size() == VALID_VECTOR_SIZE) {
354            std::string key = linkBandwidths.front();
355            std::string linkUpDownBandwidth = linkBandwidths.back();
356            std::vector<std::string> upDownBandwidthValue = CellularDataUtils::Split(linkUpDownBandwidth, ",");
357            if (upDownBandwidthValue.size() == VALID_VECTOR_SIZE) {
358                LinkBandwidthInfo linkBandwidthInfo;
359                linkBandwidthInfo.downBandwidth = (atoi)(upDownBandwidthValue.front().c_str());
360                linkBandwidthInfo.upBandwidth = (atoi)(upDownBandwidthValue.back().c_str());
361                bandwidthConfigMap_.emplace(key, linkBandwidthInfo);
362            }
363        }
364    }
365    TELEPHONY_LOGI("Slot%{public}d: BANDWIDTH_CONFIG_MAP size is %{public}zu", slotId_, bandwidthConfigMap_.size());
366    UpdateBandWidthsUseLte();
367}
368
369void DataConnectionManager::UpdateBandWidthsUseLte()
370{
371    if (!uplinkUseLte_) {
372        return;
373    }
374    std::map<std::string, LinkBandwidthInfo>::iterator iter = bandwidthConfigMap_.find("LTE");
375    if (iter != bandwidthConfigMap_.end()) {
376        LinkBandwidthInfo lteLinkBandwidthInfo = iter->second;
377        TELEPHONY_LOGI("Slot%{public}d: name is %{public}s upBandwidth = %{public}u downBandwidth = %{public}u",
378            slotId_, iter->first.c_str(), lteLinkBandwidthInfo.upBandwidth, lteLinkBandwidthInfo.downBandwidth);
379        iter = bandwidthConfigMap_.find("NR_NSA");
380        if (iter != bandwidthConfigMap_.end()) {
381            iter->second.upBandwidth = lteLinkBandwidthInfo.upBandwidth;
382        }
383        iter = bandwidthConfigMap_.find("NR_NSA_MMWAVE");
384        if (iter != bandwidthConfigMap_.end()) {
385            iter->second.upBandwidth = lteLinkBandwidthInfo.upBandwidth;
386        }
387    }
388}
389
390void DataConnectionManager::GetDefaultTcpBufferConfig()
391{
392    char tcpBufferConfig[MAX_BUFFER_SIZE] = {0};
393    GetParameter(CONFIG_TCP_BUFFER, DEFAULT_TCP_BUFFER_CONFIG, tcpBufferConfig, MAX_BUFFER_SIZE);
394    std::vector<std::string> tcpBufferVec = CellularDataUtils::Split(tcpBufferConfig, ";");
395    std::lock_guard<std::mutex> lock(tcpBufferConfigMutex_);
396    tcpBufferConfigMap_.clear();
397    for (std::string tcpBuffer : tcpBufferVec) {
398        std::vector<std::string> str = CellularDataUtils::Split(tcpBuffer, ":");
399        tcpBufferConfigMap_.emplace(str.front(), str.back());
400    }
401    TELEPHONY_LOGI("Slot%{public}d: TCP_BUFFER_CONFIG_MAP size is %{public}zu", slotId_, tcpBufferConfigMap_.size());
402}
403
404LinkBandwidthInfo DataConnectionManager::GetBandwidthsByRadioTech(const int32_t radioTech)
405{
406    LinkBandwidthInfo linkBandwidthInfo;
407    CoreManagerInner &coreInner = CoreManagerInner::GetInstance();
408    NrState nrState = coreInner.GetNrState(slotId_);
409    FrequencyType frequencyType = coreInner.GetFrequencyType(slotId_);
410    std::string radioTechName = CellularDataUtils::ConvertRadioTechToRadioName(radioTech);
411    if (radioTech == (int32_t)RadioTech::RADIO_TECHNOLOGY_LTE &&
412        (nrState == NrState::NR_NSA_STATE_DUAL_CONNECTED || nrState == NrState::NR_NSA_STATE_CONNECTED_DETECT)) {
413        if (frequencyType == FrequencyType::FREQ_TYPE_MMWAVE) {
414            radioTechName = "NR_NSA_MMWAVE";
415        } else {
416            radioTechName = "NR_NSA";
417        }
418    }
419    if (radioTechName == "NR") {
420        radioTechName = "NR_SA";
421    }
422    TELEPHONY_LOGI("Slot%{public}d: accessRadioName is %{private}s", slotId_, radioTechName.c_str());
423    std::lock_guard<std::mutex> lock(bandwidthConfigMutex_);
424    std::map<std::string, LinkBandwidthInfo>::iterator iter = bandwidthConfigMap_.find(radioTechName);
425    if (iter != bandwidthConfigMap_.end()) {
426        linkBandwidthInfo = iter->second;
427        TELEPHONY_LOGI("Slot%{public}d: name is %{private}s upBandwidth = %{public}u downBandwidth = %{public}u",
428            slotId_, iter->first.c_str(), linkBandwidthInfo.upBandwidth, linkBandwidthInfo.downBandwidth);
429    }
430    return linkBandwidthInfo;
431}
432
433std::string DataConnectionManager::GetTcpBufferByRadioTech(const int32_t radioTech)
434{
435    std::string tcpBuffer = "";
436    CoreManagerInner &coreInner = CoreManagerInner::GetInstance();
437    NrState nrState = coreInner.GetNrState(slotId_);
438    std::string radioTechName = CellularDataUtils::ConvertRadioTechToRadioName(radioTech);
439    if ((radioTech == (int32_t)RadioTech::RADIO_TECHNOLOGY_LTE ||
440        radioTech == (int32_t)RadioTech::RADIO_TECHNOLOGY_LTE_CA) &&
441        (nrState == NrState::NR_NSA_STATE_DUAL_CONNECTED || nrState == NrState::NR_NSA_STATE_CONNECTED_DETECT)) {
442        radioTechName = "NR";
443    }
444    std::lock_guard<std::mutex> lock(tcpBufferConfigMutex_);
445    std::map<std::string, std::string>::iterator iter = tcpBufferConfigMap_.find(radioTechName);
446    if (iter != tcpBufferConfigMap_.end()) {
447        tcpBuffer = iter->second;
448    }
449    return tcpBuffer;
450}
451
452void DataConnectionManager::IsNeedDoRecovery(bool needDoRecovery) const
453{
454    if (connectionMonitor_ != nullptr) {
455        connectionMonitor_->IsNeedDoRecovery(needDoRecovery);
456    }
457}
458
459void DataConnectionManager::HandleScreenStateChanged(bool isScreenOn) const
460{
461    if (connectionMonitor_ == nullptr) {
462        TELEPHONY_LOGE("Slot%{public}d: connection monitor is null", slotId_);
463        return;
464    }
465    connectionMonitor_->HandleScreenStateChanged(isScreenOn);
466}
467} // namespace Telephony
468} // namespace OHOS
469