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