• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 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 "wifi_country_code_manager.h"
17 #include <cstdint>
18 #include <sstream>
19 #include "i_ap_service.h"
20 #include "wifi_ap_hal_interface.h"
21 #include "wifi_common_event_helper.h"
22 #include "wifi_datashare_utils.h"
23 #include "wifi_errcode.h"
24 #include "wifi_global_func.h"
25 #include "wifi_logger.h"
26 #include "wifi_msg.h"
27 #include "wifi_config_center.h"
28 #include "wifi_common_util.h"
29 #include "wifi_controller_define.h"
30 
31 namespace OHOS {
32 namespace Wifi {
33 DEFINE_WIFILOG_LABEL("WifiCountryCodeManager");
34 const std::string CLASS_NAME = "WifiCountryCodeManager";
35 
~WifiCountryCodeManager()36 WifiCountryCodeManager::~WifiCountryCodeManager()
37 {
38     std::lock_guard<std::mutex> lock(m_countryCodeMutex);
39     m_codeChangeListeners.clear();
40 }
41 
GetInstance()42 WifiCountryCodeManager &WifiCountryCodeManager::GetInstance()
43 {
44     static WifiCountryCodeManager instance;
45     return instance;
46 }
47 
Init()48 ErrCode WifiCountryCodeManager::Init()
49 {
50     WIFI_LOGI("init");
51     wifiCountryCodePolicyConf_ = GetWifiCountryCodePolicy();
52     m_wifiCountryCodePolicy = std::make_shared<WifiCountryCodePolicy>(wifiCountryCodePolicyConf_);
53 #ifdef FEATURE_STA_SUPPORT
54     m_staCallback.callbackModuleName = CLASS_NAME;
55     m_staCallback.OnStaConnChanged = DealStaConnChanged;
56 #endif
57 
58 #ifdef FEATURE_AP_SUPPORT
59     m_apCallback.callbackModuleName = CLASS_NAME;
60     m_apCallback.OnApStateChangedEvent = DealApStateChanged;
61 #endif
62     return WIFI_OPT_SUCCESS;
63 }
64 
65 #ifdef FEATURE_STA_SUPPORT
GetStaCallback() const66 StaServiceCallback WifiCountryCodeManager::GetStaCallback() const
67 {
68     return m_staCallback;
69 }
70 #endif
71 
72 #ifdef FEATURE_AP_SUPPORT
GetApCallback() const73 IApServiceCallbacks WifiCountryCodeManager::GetApCallback() const
74 {
75     return m_apCallback;
76 }
77 #endif
78 
GetWifiCountryCode(std::string & wifiCountryCode) const79 void WifiCountryCodeManager::GetWifiCountryCode(std::string &wifiCountryCode) const
80 {
81     wifiCountryCode = m_wifiCountryCode;
82 }
83 
SetWifiCountryCodeFromExternal(const std::string & wifiCountryCode)84 ErrCode WifiCountryCodeManager::SetWifiCountryCodeFromExternal(const std::string &wifiCountryCode)
85 {
86     WIFI_LOGD("set wifi country code from external, externalCode=%{public}s", wifiCountryCode.c_str());
87     return UpdateWifiCountryCode(wifiCountryCode);
88 }
89 
TriggerUpdateWifiCountryCode(int triggerReason)90 void WifiCountryCodeManager::TriggerUpdateWifiCountryCode(int triggerReason)
91 {
92     if (triggerReason == TRIGGER_UPDATE_REASON_TEL_NET_CHANGE && wifiCountryCodePolicyConf_[FEATURE_MCC]) {
93         WIFI_LOGI("TEL_NET_CHANGE trigger update country code change");
94         UpdateWifiCountryCode();
95     } else if (triggerReason == TRIGGER_UPDATE_REASON_SCAN_CHANGE &&
96         wifiCountryCodePolicyConf_[FEATURE_RCV_SCAN_RESLUT] && m_wifiCountryCodePolicy != nullptr) {
97         m_wifiCountryCodePolicy->HandleScanResultAction();
98         UpdateWifiCountryCode();
99     }
100 }
101 
IsAllowUpdateWifiCountryCode()102 bool WifiCountryCodeManager::IsAllowUpdateWifiCountryCode()
103 {
104     bool ret = true;
105 
106     // The Wi-Fi connection has just succeeded. Updating the country code is allowed.
107     if (m_isFirstConnected) {
108         WIFI_LOGI("wifi first connected, allow update wifi country code");
109         m_isFirstConnected = false;
110         return ret;
111     }
112 
113     std::map <int, WifiLinkedInfo> allLinkedInfo = WifiConfigCenter::GetInstance().GetAllWifiLinkedInfo();
114     for (auto item : allLinkedInfo) {
115         if (item.second.connState == ConnState::CONNECTED) {
116             WIFI_LOGI("wifi connected, not allow update wifi country code, instId=%{public}d", item.first);
117             ret = false;
118             break;
119         }
120     }
121     return ret;
122 }
123 
124 /*
125  * Scenarios that trigger country code update, with configuration files controlling the effectiveness of the scenario:
126  * 1 Received a telephone network search state change notify;
127  * 2 Wifi open success;
128  * 3 Softap started;
129  * 4 Update the country code by calling the SetWifiCountryCode interface externally;
130  * 5 Report the scanning result.
131  */
UpdateWifiCountryCode(const std::string & externalCode)132 ErrCode WifiCountryCodeManager::UpdateWifiCountryCode(const std::string &externalCode)
133 {
134     if (!IsAllowUpdateWifiCountryCode()) {
135         return WIFI_OPT_FAILED;
136     }
137     std::string wifiCountryCode;
138     if (!externalCode.empty() && !IsValidCountryCode(externalCode)) {
139         WIFI_LOGI("external set wifi country code, code=%{public}s", externalCode.c_str());
140         wifiCountryCode = externalCode;
141     } else if (m_wifiCountryCodePolicy == nullptr ||
142         m_wifiCountryCodePolicy->CalculateWifiCountryCode(wifiCountryCode) == WIFI_OPT_FAILED) {
143         WIFI_LOGE("calculate wifi country code failed");
144         return WIFI_OPT_FAILED;
145     }
146     StrToUpper(wifiCountryCode);
147     WIFI_LOGI("calculate wifi country code result:%{public}s", wifiCountryCode.c_str());
148     UpdateWifiCountryCodeCache(wifiCountryCode);
149     m_wifiCountryCode = wifiCountryCode;
150     NotifyWifiCountryCodeChangeListeners(wifiCountryCode);
151     return WIFI_OPT_SUCCESS;
152 }
153 
NotifyWifiCountryCodeChangeListeners(const std::string & wifiCountryCode)154 void WifiCountryCodeManager::NotifyWifiCountryCodeChangeListeners(const std::string &wifiCountryCode)
155 {
156     std::lock_guard<std::mutex> lock(m_countryCodeMutex);
157     for (auto &callBackItem : m_codeChangeListeners) {
158         WIFI_LOGI("notify wifi country code change, module name=%{public}s", callBackItem.first.c_str());
159         callBackItem.second->OnWifiCountryCodeChanged(wifiCountryCode);
160     }
161 }
162 
RegisterWifiCountryCodeChangeListener(const std::shared_ptr<IWifiCountryCodeChangeListener> & listener)163 ErrCode WifiCountryCodeManager::RegisterWifiCountryCodeChangeListener(
164     const std::shared_ptr<IWifiCountryCodeChangeListener> &listener)
165 {
166     std::lock_guard<std::mutex> lock(m_countryCodeMutex);
167     if (listener->GetListenerModuleName().empty()) {
168         WIFI_LOGE("register fail, listener module name is null");
169         return WIFI_OPT_FAILED;
170     }
171     m_codeChangeListeners.insert_or_assign(listener->GetListenerModuleName(), listener);
172     WIFI_LOGI("register success, listener module name: %{public}s", listener->GetListenerModuleName().c_str());
173     return WIFI_OPT_SUCCESS;
174 }
175 
UnregisterWifiCountryCodeChangeListener(const std::shared_ptr<IWifiCountryCodeChangeListener> & listener)176 ErrCode WifiCountryCodeManager::UnregisterWifiCountryCodeChangeListener(
177     const std::shared_ptr<IWifiCountryCodeChangeListener> &listener)
178 {
179     return UnregisterWifiCountryCodeChangeListener(listener->GetListenerModuleName());
180 }
181 
UnregisterWifiCountryCodeChangeListener(const std::string & moduleName)182 ErrCode WifiCountryCodeManager::UnregisterWifiCountryCodeChangeListener(const std::string &moduleName)
183 {
184     std::lock_guard<std::mutex> lock(m_countryCodeMutex);
185     if (moduleName.empty()) {
186         WIFI_LOGE("unregister fail, listener module name is null");
187         return WIFI_OPT_FAILED;
188     }
189     int ret = static_cast<int>(m_codeChangeListeners.erase(moduleName));
190     WIFI_LOGI("unregister ret=%{public}d, listener module name: %{public}s", ret, moduleName.c_str());
191     return ret > 0 ? WIFI_OPT_SUCCESS : WIFI_OPT_FAILED;
192 }
193 
194 #ifdef FEATURE_STA_SUPPORT
DealStaOpened(int instId)195 void WifiCountryCodeManager::DealStaOpened(int instId)
196 {
197     WIFI_LOGI("wifi opened, id=%{public}d", instId);
198     WifiCountryCodeManager::GetInstance().UpdateWifiCountryCode();
199 }
200 
DealStaStopped(int instId)201 void WifiCountryCodeManager::DealStaStopped(int instId)
202 {
203     WIFI_LOGI("wifi close, id=%{public}d", instId);
204     std::string moduleName = "StaService_" + std::to_string(instId);
205     WifiCountryCodeManager::GetInstance().UnregisterWifiCountryCodeChangeListener(moduleName);
206 }
207 #endif
208 
209 #ifdef FEATURE_STA_SUPPORT
DealStaConnChanged(OperateResState state,const WifiLinkedInfo & info,int instId)210 void WifiCountryCodeManager::DealStaConnChanged(OperateResState state, const WifiLinkedInfo &info, int instId)
211 {
212     WIFI_LOGD("wifi connection state change, state=%{public}d, id=%{public}d", state, instId);
213     if (state == OperateResState::CONNECT_AP_CONNECTED) {
214         WifiCountryCodeManager::GetInstance().m_isFirstConnected = true;
215         WifiCountryCodeManager::GetInstance().UpdateWifiCountryCode();
216     }
217 }
218 #endif
219 
220 #ifdef FEATURE_AP_SUPPORT
DealApStateChanged(ApState state,int id,int hotspotMode)221 void WifiCountryCodeManager::DealApStateChanged(ApState state, int id, int hotspotMode)
222 {
223     WIFI_LOGI("ap state change, state=%{public}d, id=%{public}d", state, id);
224     if (state == ApState::AP_STATE_STARTED) {
225         WifiCountryCodeManager::GetInstance().UpdateWifiCountryCode();
226     } else if (state != ApState::AP_STATE_STARTING && state != ApState::AP_STATE_STARTED) {
227         std::string moduleName = "ApService_" + std::to_string(id);
228         WifiCountryCodeManager::GetInstance().UnregisterWifiCountryCodeChangeListener(moduleName);
229         WriteSoftApOperateHiSysEvent(static_cast<int>(SoftApChrEventType::SOFT_AP_OPEN_SUC_CNT));
230     }
231 }
232 #endif
233 
UpdateWifiCountryCodeCache(const std::string & wifiCountryCode)234 ErrCode WifiCountryCodeManager::UpdateWifiCountryCodeCache(const std::string &wifiCountryCode)
235 {
236     if (wifiCountryCode.empty() || !IsValidCountryCode(wifiCountryCode)) {
237         WIFI_LOGE("wifi country code is empty or invalid");
238         return WIFI_OPT_FAILED;
239     }
240     int ret = SetParamValue(WIFI_COUNTRY_CODE_DYNAMIC_UPDATE_KEY, wifiCountryCode.c_str());
241     std::string retStr = ret == 0 ? "success" : "fail, ret=" + std::to_string(ret);
242     WIFI_LOGI("update wifi country code cache %{public}s", retStr.c_str());
243     return ret == 0 ? WIFI_OPT_SUCCESS : WIFI_OPT_FAILED;
244 }
245 
GetWifiCountryCodePolicy()246 std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> WifiCountryCodeManager::GetWifiCountryCodePolicy()
247 {
248     char preValue[WIFI_COUNTRY_CODE_SIZE] = {0};
249     int errorCode = GetParamValue(WIFI_COUNTRY_CODE_CONFIG,
250         WIFI_COUNTRY_CODE_CONFIG_DEFAULT, preValue, WIFI_COUNTRY_CODE_SIZE);
251     int policyConf = 0;
252     if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE) {
253         WIFI_LOGI("get wifi country code policy config fail, use policyConf=0");
254         return std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN>(policyConf);
255     }
256     std::string policyStr(preValue);
257     policyConf = CheckDataLegal(policyStr);
258     WIFI_LOGI("get wifi country code policy config is %{public}d", policyConf);
259     return std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN>(policyConf);
260 }
261 }
262 }