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 }