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 "apn_holder.h"
17
18#include "cellular_data_event_code.h"
19#include "cellular_data_state_machine.h"
20#include "data_disconnect_params.h"
21#include "apn_manager.h"
22namespace OHOS {
23namespace Telephony {
24namespace {
25    constexpr int32_t SYSTEM_UID = 1e4;
26    std::shared_mutex reqUidsMutex_;
27}
28const std::map<std::string, int32_t> ApnHolder::apnTypeDataProfileMap_ {
29    {DATA_CONTEXT_ROLE_DEFAULT, DATA_PROFILE_DEFAULT},
30    {DATA_CONTEXT_ROLE_MMS, DATA_PROFILE_MMS},
31    {DATA_CONTEXT_ROLE_SUPL, DATA_PROFILE_SUPL},
32    {DATA_CONTEXT_ROLE_DUN, DATA_PROFILE_DUN},
33    {DATA_CONTEXT_ROLE_IA, DATA_PROFILE_IA},
34    {DATA_CONTEXT_ROLE_XCAP, DATA_PROFILE_XCAP}
35};
36
37ApnHolder::ApnHolder(const std::string &apnType, const int32_t priority) : apnType_(apnType), priority_(priority) {}
38
39ApnHolder::~ApnHolder() = default;
40
41sptr<ApnItem> ApnHolder::GetNextRetryApn() const
42{
43    return retryPolicy_.GetNextRetryApnItem();
44}
45
46void ApnHolder::SetAllMatchedApns(std::vector<sptr<ApnItem>> &matchedApns)
47{
48    retryPolicy_.SetMatchedApns(matchedApns);
49}
50
51int64_t ApnHolder::GetRetryDelay(int32_t cause, int32_t suggestTime, RetryScene scene, int32_t slotId)
52{
53    return retryPolicy_.GetNextRetryDelay(apnType_, cause, suggestTime, scene, slotId);
54}
55
56void ApnHolder::SetCurrentApn(sptr<ApnItem> &apnItem)
57{
58    apnItem_ = apnItem;
59}
60
61sptr<ApnItem> ApnHolder::GetCurrentApn() const
62{
63    return apnItem_;
64}
65
66void ApnHolder::AddUid(uint32_t uid)
67{
68    std::unique_lock<std::shared_mutex> lock(reqUidsMutex_);
69    if (reqUids_.find(uid) != reqUids_.end()) {
70        return;
71    }
72    reqUids_.insert(uid);
73}
74
75void ApnHolder::RemoveUid(uint32_t uid)
76{
77    std::unique_lock<std::shared_mutex> lock(reqUidsMutex_);
78    auto it = reqUids_.find(uid);
79    if (it != reqUids_.end()) {
80        reqUids_.erase(it);
81        return;
82    }
83}
84
85void ApnHolder::SetApnState(ApnProfileState state)
86{
87    if (apnState_ != state) {
88        apnState_ = state;
89    }
90    if (apnState_ == PROFILE_STATE_FAILED) {
91        retryPolicy_.ClearRetryApns();
92    }
93}
94
95ApnProfileState ApnHolder::GetApnState() const
96{
97    return apnState_;
98}
99
100bool ApnHolder::IsDataCallEnabled() const
101{
102    return dataCallEnabled_;
103}
104
105std::string ApnHolder::GetApnType() const
106{
107    return apnType_;
108}
109
110void ApnHolder::ReleaseDataConnection()
111{
112    if (cellularDataStateMachine_ == nullptr) {
113        TELEPHONY_LOGE("cellularDataStateMachine_ is null");
114        return;
115    }
116    std::unique_ptr<DataDisconnectParams> object =
117        std::make_unique<DataDisconnectParams>(apnType_, DisConnectionReason::REASON_CLEAR_CONNECTION);
118    if (object == nullptr) {
119        TELEPHONY_LOGE("ClearConnection fail, object is null");
120        return;
121    }
122    apnState_ = PROFILE_STATE_DISCONNECTING;
123    AppExecFwk::InnerEvent::Pointer event =
124        AppExecFwk::InnerEvent::Get(CellularDataEventCode::MSG_SM_DISCONNECT, object);
125    cellularDataStateMachine_->SendEvent(event);
126}
127
128int32_t ApnHolder::GetProfileId(const std::string &apnType) const
129{
130    std::map<std::string, int32_t>::const_iterator it = apnTypeDataProfileMap_.find(apnType);
131    if (it != apnTypeDataProfileMap_.end()) {
132        return it->second;
133    }
134    TELEPHONY_LOGI("this apnType is not in apnTypeDataProfileMap.");
135    return DATA_PROFILE_DEFAULT;
136}
137
138void ApnHolder::SetCellularDataStateMachine(const std::shared_ptr<CellularDataStateMachine> &stateMachine)
139{
140    cellularDataStateMachine_ = stateMachine;
141}
142
143std::shared_ptr<CellularDataStateMachine> ApnHolder::GetCellularDataStateMachine() const
144{
145    return cellularDataStateMachine_;
146}
147
148uint64_t ApnHolder::GetCapability() const
149{
150    return capability_;
151}
152
153int32_t ApnHolder::GetPriority() const
154{
155    return priority_;
156}
157
158HasSystemUse ApnHolder::GetUidStatus() const
159{
160    std::unique_lock<std::shared_mutex> lock(reqUidsMutex_);
161    for (auto item : reqUids_) {
162        if (item < SYSTEM_UID) {
163            return HasSystemUse::HAS;
164        }
165    }
166    return HasSystemUse::NOT_HAS;
167}
168
169void ApnHolder::RequestCellularData(const NetRequest &netRequest)
170{
171    for (const NetRequest &request : netRequests_) {
172        if ((netRequest.capability == request.capability) && (netRequest.ident == request.ident)) {
173            return;
174        }
175    }
176    netRequests_.push_back(netRequest);
177    capability_ = netRequest.capability;
178    dataCallEnabled_ = true;
179}
180
181bool ApnHolder::ReleaseCellularData(const NetRequest &netRequest)
182{
183    for (std::vector<NetRequest>::const_iterator it = netRequests_.begin(); it != netRequests_.end();) {
184        if ((netRequest.capability == it->capability) && (netRequest.ident == it->ident)) {
185            it = netRequests_.erase(it);
186            if (netRequests_.empty()) {
187                dataCallEnabled_ = false;
188                return true;
189            }
190        } else {
191            it++;
192        }
193    }
194    return false;
195}
196
197void ApnHolder::ReleaseAllCellularData()
198{
199    TELEPHONY_LOGI("clear all cellular data");
200    netRequests_.clear();
201    if (netRequests_.empty()) {
202        dataCallEnabled_ = false;
203    }
204}
205
206bool ApnHolder::IsEmergencyType() const
207{
208    return apnType_ == DATA_CONTEXT_ROLE_EMERGENCY;
209}
210
211bool ApnHolder::IsMmsType() const
212{
213    return apnType_ == DATA_CONTEXT_ROLE_MMS;
214}
215
216void ApnHolder::InitialApnRetryCount()
217{
218    retryPolicy_.InitialRetryCountValue();
219}
220
221bool ApnHolder::IsSameMatchedApns(std::vector<sptr<ApnItem>> newMatchedApns, bool roamingState)
222{
223    std::vector<sptr<ApnItem>> currentMatchedApns = retryPolicy_.GetMatchedApns();
224    if (currentMatchedApns.empty() || newMatchedApns.empty()) {
225        TELEPHONY_LOGE("newMatchedApns or oldMatchedApns is empty");
226        return false;
227    }
228    if (currentMatchedApns.size() != newMatchedApns.size()) {
229        TELEPHONY_LOGI("newMatchedApns and oldMatchedApns are not equal in size");
230        return false;
231    }
232    for (const sptr<ApnItem> &newApnItem : newMatchedApns) {
233        bool canHandle = false;
234        for (const sptr<ApnItem> &oldApnItem : currentMatchedApns) {
235            if (IsSameApnItem(newApnItem, oldApnItem, roamingState)) {
236                canHandle = true;
237                break;
238            }
239        }
240        if (!canHandle) {
241            return false;
242        }
243    }
244    return true;
245}
246
247bool ApnHolder::IsSameApnItem(const sptr<ApnItem> &newApnItem,
248                              const sptr<ApnItem> &oldApnItem,
249                              bool roamingState)
250{
251    if (newApnItem == nullptr || oldApnItem == nullptr) {
252        TELEPHONY_LOGE("newApnItem or oldApnItem is null");
253        return false;
254    }
255    bool isSameProtocol = false;
256    if (roamingState) {
257        isSameProtocol = std::strcmp(newApnItem->attr_.roamingProtocol_, oldApnItem->attr_.roamingProtocol_) == 0;
258    } else {
259        isSameProtocol = std::strcmp(newApnItem->attr_.protocol_, oldApnItem->attr_.protocol_) == 0;
260    }
261    return isSameProtocol && newApnItem->attr_.profileId_ == oldApnItem->attr_.profileId_ &&
262        newApnItem->attr_.authType_ == oldApnItem->attr_.authType_ &&
263        newApnItem->attr_.isRoamingApn_ == oldApnItem->attr_.isRoamingApn_ &&
264        newApnItem->attr_.isEdited_ == oldApnItem->attr_.isEdited_ &&
265        std::strcmp(newApnItem->attr_.types_, oldApnItem->attr_.types_) == 0 &&
266        std::strcmp(newApnItem->attr_.numeric_, oldApnItem->attr_.numeric_) == 0 &&
267        std::strcmp(newApnItem->attr_.apn_, oldApnItem->attr_.apn_) == 0 &&
268        std::strcmp(newApnItem->attr_.apnName_, oldApnItem->attr_.apnName_) == 0 &&
269        std::strcmp(newApnItem->attr_.user_, oldApnItem->attr_.user_) == 0 &&
270        std::strcmp(newApnItem->attr_.password_, oldApnItem->attr_.password_) == 0 &&
271        std::strcmp(newApnItem->attr_.homeUrl_, oldApnItem->attr_.homeUrl_) == 0 &&
272        std::strcmp(newApnItem->attr_.proxyIpAddress_, oldApnItem->attr_.proxyIpAddress_) == 0 &&
273        std::strcmp(newApnItem->attr_.mmsIpAddress_, oldApnItem->attr_.mmsIpAddress_) == 0;
274}
275
276bool ApnHolder::IsCompatibleApnItem(const sptr<ApnItem> &newApnItem, const sptr<ApnItem> &oldApnItem,
277    bool roamingState)
278{
279    if (newApnItem == nullptr || oldApnItem == nullptr) {
280        TELEPHONY_LOGE("newApnItem or oldApnItem is null");
281        return false;
282    }
283    bool isSameProtocol = false;
284    if (roamingState) {
285        isSameProtocol = std::strcmp(newApnItem->attr_.roamingProtocol_, oldApnItem->attr_.roamingProtocol_) == 0;
286    } else {
287        isSameProtocol = std::strcmp(newApnItem->attr_.protocol_, oldApnItem->attr_.protocol_) == 0;
288    }
289    return isSameProtocol && newApnItem->attr_.profileId_ == oldApnItem->attr_.profileId_ &&
290        newApnItem->attr_.authType_ == oldApnItem->attr_.authType_ &&
291        std::strcmp(newApnItem->attr_.types_, oldApnItem->attr_.types_) == 0 &&
292        std::strcmp(newApnItem->attr_.numeric_, oldApnItem->attr_.numeric_) == 0 &&
293        std::strcmp(newApnItem->attr_.apn_, oldApnItem->attr_.apn_) == 0 &&
294        std::strcmp(newApnItem->attr_.apnName_, oldApnItem->attr_.apnName_) == 0 &&
295        std::strcmp(newApnItem->attr_.user_, oldApnItem->attr_.user_) == 0 &&
296        std::strcmp(newApnItem->attr_.password_, oldApnItem->attr_.password_) == 0 &&
297        std::strcmp(newApnItem->attr_.proxyIpAddress_, oldApnItem->attr_.proxyIpAddress_) == 0 &&
298        std::strcmp(newApnItem->attr_.mmsIpAddress_, oldApnItem->attr_.mmsIpAddress_) == 0;
299}
300
301void ApnHolder::MarkCurrentApnBad()
302{
303    if (apnItem_ != nullptr) {
304        apnItem_->MarkBadApn(true);
305    }
306}
307
308void ApnHolder::ClearCurrentApnBad()
309{
310    if (apnItem_ != nullptr) {
311        apnItem_->MarkBadApn(false);
312    }
313}
314} // namespace Telephony
315} // namespace OHOS