1 /*
2 * Copyright (C) 2021-2022 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_policy.h"
17 #include <memory>
18 #ifdef TELEPHONE_CORE_SERVICE_ENABLE
19 #include "core_service_client.h"
20 #endif
21 #ifdef I18N_INTL_UTIL_ENABLE
22 #include "locale_config.h"
23 #endif
24 #include "uri.h"
25 #include "wifi_country_code_manager.h"
26 #include "wifi_global_func.h"
27 #include "wifi_logger.h"
28 #include "wifi_msg.h"
29 #include "wifi_config_center.h"
30
31 namespace OHOS {
32 namespace Wifi {
33 DEFINE_WIFILOG_LABEL("WifiCountryCodePolicy");
34
WifiCountryCodePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)35 WifiCountryCodePolicy::WifiCountryCodePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)
36 {
37 CreatePolicy(wifiCountryCodePolicyConf);
38 }
39
CreatePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)40 void WifiCountryCodePolicy::CreatePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)
41 {
42 WIFI_LOGI("create wifi country code policy");
43 m_policyList.emplace_back(
44 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByFactory, this, std::placeholders::_1));
45 if (wifiCountryCodePolicyConf[FEATURE_MCC]) {
46 m_policyList.emplace_back(
47 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByMcc, this, std::placeholders::_1));
48 }
49 if (wifiCountryCodePolicyConf[FEATURE_RCV_AP_CONNECTED]) {
50 m_policyList.emplace_back(
51 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByAP, this, std::placeholders::_1));
52 }
53 if (wifiCountryCodePolicyConf[FEATURE_RCV_SCAN_RESLUT]) {
54 m_policyList.emplace_back(
55 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByScanResult, this, std::placeholders::_1));
56 }
57 if (wifiCountryCodePolicyConf[FEATURE_USE_REGION]) {
58 m_policyList.emplace_back(
59 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByRegion, this, std::placeholders::_1));
60 }
61 if (wifiCountryCodePolicyConf[FEATURE_USE_ZZ]) {
62 m_policyList.emplace_back(
63 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByDefaultZZ, this, std::placeholders::_1));
64 }
65 m_policyList.emplace_back(
66 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByCache, this, std::placeholders::_1));
67 m_policyList.emplace_back(
68 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByDefaultRegion, this, std::placeholders::_1));
69 m_policyList.emplace_back(
70 std::bind(&WifiCountryCodePolicy::GetWifiCountryCodeByDefault, this, std::placeholders::_1));
71 }
72
CalculateWifiCountryCode(std::string & wifiCountryCode)73 ErrCode WifiCountryCodePolicy::CalculateWifiCountryCode(std::string &wifiCountryCode)
74 {
75 for (const auto &policy : m_policyList) {
76 if (policy(wifiCountryCode) == WIFI_OPT_SUCCESS) {
77 return WIFI_OPT_SUCCESS;
78 }
79 }
80 return WIFI_OPT_FAILED;
81 }
82
GetWifiCountryCodeByFactory(std::string & wifiCountryCode)83 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByFactory(std::string &wifiCountryCode)
84 {
85 char roRunModeValue[WIFI_COUNTRY_CODE_RUN_MODE_SIZE] = {0};
86 int errorCode = GetParamValue(WIFI_COUNTRY_CODE_RUN_MODE, DEFAULT_RO_RUN_MODE, roRunModeValue,
87 WIFI_COUNTRY_CODE_RUN_MODE_SIZE);
88 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE || strcasecmp(FACTORY_RO_RUN_MODE, roRunModeValue) != 0) {
89 WIFI_LOGI("wifi country code factory mode does not take effect or fail, ret=%{public}d, "
90 "runMode=%{public}s", errorCode, roRunModeValue);
91 return WIFI_OPT_FAILED;
92 }
93 char factoryWifiCountryCodeValue[FACTORY_WIFI_COUNTRY_CODE_SIZE] = {0};
94 errorCode = GetParamValue(FACTORY_WIFI_COUNTRY_CODE, DEFAULT_WIFI_COUNTRY_CODE,
95 factoryWifiCountryCodeValue, FACTORY_WIFI_COUNTRY_CODE_SIZE);
96 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE) {
97 WIFI_LOGI("get wifi country code by factory fail, errorCode=%{public}d", errorCode);
98 return WIFI_OPT_FAILED;
99 }
100 if (!IsValidCountryCode(factoryWifiCountryCodeValue)) {
101 WIFI_LOGI("get wifi country code by factory fail, code invalid, code=%{public}s",
102 factoryWifiCountryCodeValue);
103 return WIFI_OPT_FAILED;
104 }
105 wifiCountryCode = factoryWifiCountryCodeValue;
106 WIFI_LOGI("get wifi country code by factory success, code=%{public}s", wifiCountryCode.c_str());
107 return WIFI_OPT_SUCCESS;
108 }
109
GetWifiCountryCodeByMcc(std::string & wifiCountryCode)110 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByMcc(std::string &wifiCountryCode)
111 {
112 // get cached plmn
113 char cachedPlmn[OPERATOR_NUMERIC_SIZE] = {0};
114 int errorCode = GetParamValue(OPERATOR_NUMERIC_KEY, DEFAULT_OPERATOR_NUMERIC, cachedPlmn, OPERATOR_NUMERIC_SIZE);
115 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE || strcasecmp(DEFAULT_OPERATOR_NUMERIC, cachedPlmn) == 0) {
116 WIFI_LOGE("get wifi country code by cached mcc fail, ret=%{public}d, cachedPlmn=%{public}s",
117 errorCode, cachedPlmn);
118 return WIFI_OPT_FAILED;
119 }
120 std::string cachedPlmnStr(cachedPlmn);
121 int integerCachedMcc = ConvertStringToInt(cachedPlmnStr.substr(PLMN_SUBSTR_LEFT, PLMN_SUBSTR_RIGHT));
122 if (ConvertMncToIso(integerCachedMcc, wifiCountryCode) != true) {
123 WIFI_LOGE("get wifi country code by cached mcc fail, cached plmn invalid, mcc=%{public}d", integerCachedMcc);
124 return WIFI_OPT_FAILED;
125 }
126
127 // get dynamic plmn
128 std::string dynamicPlmn;
129 #ifdef TELEPHONE_CORE_SERVICE_ENABLE
130 dynamicPlmn = Str16ToStr8(Telephony::CoreServiceClient::GetInstance().GetOperatorNumeric(SLOT_ID));
131 #endif
132 if (dynamicPlmn.empty() || dynamicPlmn.length() < PLMN_LEN) {
133 WIFI_LOGI("get wifi country code by dynamic mcc fail, plmn invalid, plmn=%{public}s, use cached plmn, "
134 "cache code=%{public}s", dynamicPlmn.c_str(), wifiCountryCode.c_str());
135 return WIFI_OPT_SUCCESS;
136 }
137 int integerMcc = ConvertStringToInt(dynamicPlmn.substr(PLMN_SUBSTR_LEFT, PLMN_SUBSTR_RIGHT));
138 if (ConvertMncToIso(integerMcc, wifiCountryCode) != true) {
139 WIFI_LOGI("get wifi country code by dynamic mcc fail, convert fail, mcc=%{public}d, use cached plmn, "
140 "cache code=%{public}s", integerMcc, wifiCountryCode.c_str());
141 return WIFI_OPT_SUCCESS;
142 }
143 WIFI_LOGI("get wifi country code by dynamic mcc success, mcc=%{public}d, code=%{public}s",
144 integerMcc, wifiCountryCode.c_str());
145 return WIFI_OPT_SUCCESS;
146 }
147
HandleScanResultAction()148 void WifiCountryCodePolicy::HandleScanResultAction()
149 {
150 std::string tempWifiCountryCode;
151 if (StatisticCountryCodeFromScanResult(tempWifiCountryCode) != WIFI_OPT_SUCCESS) {
152 m_wifiCountryCodeFromScanResults = "";
153 return;
154 }
155 if (!IsValidCountryCode(tempWifiCountryCode)) {
156 WIFI_LOGE("the country code obtained from the scann result is invalid, code=%{public}s",
157 tempWifiCountryCode.c_str());
158 m_wifiCountryCodeFromScanResults = "";
159 return;
160 }
161 m_wifiCountryCodeFromScanResults = tempWifiCountryCode;
162 }
163
IsContainBssid(const std::vector<std::string> & bssidList,const std::string & bssid)164 bool WifiCountryCodePolicy::IsContainBssid(const std::vector<std::string> &bssidList, const std::string &bssid)
165 {
166 if (bssidList.size() == 0 || bssid.empty()) {
167 return false;
168 }
169 return std::find(bssidList.begin(), bssidList.end(), bssid) != bssidList.end();
170 }
171
StatisticCountryCodeFromScanResult(std::string & wifiCountryCode)172 ErrCode WifiCountryCodePolicy::StatisticCountryCodeFromScanResult(std::string &wifiCountryCode)
173 {
174 std::vector<WifiScanInfo> results;
175 WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(results);
176 if (results.size() == 0) {
177 WIFI_LOGI("get scanResult size is 0");
178 return WIFI_OPT_FAILED;
179 }
180 std::vector<std::string> bssidVector;
181 for (auto &scanInfo : results) {
182 std::string tempWifiCountryCode;
183 ErrCode errorCode = ParseCountryCodeElement(scanInfo.infoElems, tempWifiCountryCode);
184 if (errorCode == WIFI_OPT_FAILED || scanInfo.bssid.empty() || tempWifiCountryCode.empty()) {
185 continue;
186 }
187 StrToUpper(tempWifiCountryCode);
188 m_bssidAndCountryCodeMap.insert_or_assign(scanInfo.bssid, tempWifiCountryCode);
189 bssidVector.push_back(scanInfo.bssid);
190 }
191 m_allBssidVector.push_back(bssidVector);
192 if (m_allBssidVector.size() > MAX_SCAN_SAVED_SIZE) {
193 for (const std::string &bssid : m_allBssidVector[BSSID_VECTOR_INDEX_ZERO]) {
194 if (!IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_ONE], bssid) &&
195 !IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_TWO], bssid) &&
196 !IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_THREE], bssid)) {
197 m_bssidAndCountryCodeMap.erase(bssid); // remove the ap that have not been scanned recently
198 }
199 }
200 m_allBssidVector.erase(m_allBssidVector.begin());
201 }
202 return FindLargestCountCountryCode(wifiCountryCode);
203 }
204
FindLargestCountCountryCode(std::string & wifiCountryCode)205 ErrCode WifiCountryCodePolicy::FindLargestCountCountryCode(std::string &wifiCountryCode)
206 {
207 std::map<std::string, int> codeCount; // counting the number of different country codes
208 for (const auto &info : m_bssidAndCountryCodeMap) {
209 codeCount.insert_or_assign(info.second, codeCount[info.second] + 1);
210 }
211 std::vector<std::pair<std::string, int>> sortCode(codeCount.begin(), codeCount.end());
212 sort(sortCode.begin(), sortCode.end(), [](const std::pair<std::string, int> &a,
213 const std::pair<std::string, int> &b) {
214 return a.second > b.second;
215 });
216 if (sortCode.size() == 0) {
217 WIFI_LOGI("country code count is zero");
218 return WIFI_OPT_FAILED;
219 }
220 if (sortCode.size() == 1) {
221 std::pair<std::string, int> oneCode = sortCode[0];
222 wifiCountryCode = oneCode.first;
223 WIFI_LOGI("only one country, code=%{public}s", wifiCountryCode.c_str());
224 return WIFI_OPT_SUCCESS;
225 }
226 std::pair<std::string, int> firstCode = sortCode[0];
227 std::pair<std::string, int> secondCode = sortCode[1];
228 if (firstCode.second == secondCode.second) {
229 WIFI_LOGI("contains two country codes with the same count and the largest count, unable to make decisions,"
230 " code=%{public}s|%{public}s, count=%{public}d",
231 firstCode.first.c_str(), secondCode.first.c_str(), firstCode.second);
232 return WIFI_OPT_FAILED;
233 }
234 wifiCountryCode = firstCode.first;
235 WIFI_LOGI("largest num of country code=%{public}s", wifiCountryCode.c_str());
236 return WIFI_OPT_SUCCESS;
237 }
238
ParseCountryCodeElement(const std::vector<WifiInfoElem> & infoElems,std::string & wifiCountryCode)239 ErrCode WifiCountryCodePolicy::ParseCountryCodeElement(
240 const std::vector<WifiInfoElem> &infoElems, std::string &wifiCountryCode)
241 {
242 if (infoElems.empty()) {
243 return WIFI_OPT_FAILED;
244 }
245 for (const auto &ie : infoElems) {
246 if (ie.id != COUNTRY_CODE_EID || ie.content.size() < WIFI_COUNTRY_CODE_LEN) {
247 continue;
248 }
249 std::string tempWifiCountryCode;
250 for (int i = 0 ; i < WIFI_COUNTRY_CODE_LEN; i++) {
251 tempWifiCountryCode.push_back(ie.content[i]);
252 }
253 if (!IsValidCountryCode(tempWifiCountryCode)) {
254 continue;
255 }
256 wifiCountryCode = tempWifiCountryCode;
257 return WIFI_OPT_SUCCESS;
258 }
259 return WIFI_OPT_FAILED;
260 }
261
GetWifiCountryCodeByAP(std::string & wifiCountryCode)262 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByAP(std::string &wifiCountryCode)
263 {
264 WifiLinkedInfo result;
265 WifiConfigCenter::GetInstance().GetLinkedInfo(result);
266 if (static_cast<int>(OHOS::Wifi::ConnState::CONNECTED) != result.connState) {
267 return WIFI_OPT_FAILED;
268 }
269 std::vector<WifiScanInfo> scanResults;
270 WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(scanResults);
271 if (scanResults.empty()) {
272 return WIFI_OPT_FAILED;
273 }
274 for (auto &info : scanResults) {
275 if (strcasecmp(info.bssid.c_str(), result.bssid.c_str()) == 0 &&
276 ParseCountryCodeElement(info.infoElems, wifiCountryCode) == WIFI_OPT_SUCCESS) {
277 WIFI_LOGI("get wifi country code by ap success, code=%{public}s", wifiCountryCode.c_str());
278 return WIFI_OPT_SUCCESS;
279 }
280 }
281 WIFI_LOGI("get wifi country code by ap fail, the country code of the AP is incorrect or empty");
282 return WIFI_OPT_FAILED;
283 }
284
GetWifiCountryCodeByScanResult(std::string & wifiCountryCode)285 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByScanResult(std::string &wifiCountryCode)
286 {
287 // if wifi state is not ENABLED, do not obtain the country code from the scan results
288 if (WifiConfigCenter::GetInstance().GetWifiState(SLOT_ID) != static_cast<int>(WifiState::ENABLED) ||
289 m_wifiCountryCodeFromScanResults.empty()) {
290 WIFI_LOGI("get wifi country code by scan result fail, result empty");
291 return WIFI_OPT_FAILED;
292 }
293 wifiCountryCode = m_wifiCountryCodeFromScanResults;
294 WIFI_LOGI("get wifi country code by scan result success, code=%{public}s", wifiCountryCode.c_str());
295 return WIFI_OPT_SUCCESS;
296 }
297
GetWifiCountryCodeByRegion(std::string & wifiCountryCode)298 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByRegion(std::string &wifiCountryCode)
299 {
300 // the user selects an area in settings
301 std::string tempWifiCountryCode;
302 #ifdef I18N_INTL_UTIL_ENABLE
303 tempWifiCountryCode = Global::I18n::LocaleConfig::GetSystemRegion();
304 #endif
305 if (tempWifiCountryCode.empty() || !IsValidCountryCode(tempWifiCountryCode)) {
306 WIFI_LOGE("get wifi country code by region fail, code=%{public}s", tempWifiCountryCode.c_str());
307 return WIFI_OPT_FAILED;
308 }
309 wifiCountryCode = tempWifiCountryCode;
310 WIFI_LOGI("get wifi country code by region success, code=%{public}s", wifiCountryCode.c_str());
311 return WIFI_OPT_SUCCESS;
312 }
313
GetWifiCountryCodeByDefaultZZ(std::string & wifiCountryCode)314 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByDefaultZZ(std::string &wifiCountryCode)
315 {
316 wifiCountryCode = DEFAULT_WIFI_COUNTRY_CODE_ZZ;
317 WIFI_LOGI("get wifi country code by default ZZ success, code=%{public}s",
318 DEFAULT_WIFI_COUNTRY_CODE_ZZ);
319 return WIFI_OPT_SUCCESS;
320 }
321
GetWifiCountryCodeByCache(std::string & wifiCountryCode)322 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByCache(std::string &wifiCountryCode)
323 {
324 char tempWifiCountryCode[WIFI_COUNTRY_CODE_DYNAMIC_UPDATE_SIZE] = {0};
325 int ret = GetParamValue(WIFI_COUNTRY_CODE_DYNAMIC_UPDATE_KEY, DEFAULT_WIFI_COUNTRY_CODE,
326 tempWifiCountryCode, WIFI_COUNTRY_CODE_DYNAMIC_UPDATE_SIZE);
327 if (ret <= SYSTEM_PARAMETER_ERROR_CODE) {
328 WIFI_LOGE("get wifi country code by cache fail, ret=%{public}d", ret);
329 return WIFI_OPT_FAILED;
330 }
331 if (!IsValidCountryCode(tempWifiCountryCode)) {
332 WIFI_LOGE("get wifi country code by cache fail, code invalid, code=%{public}s", tempWifiCountryCode);
333 return WIFI_OPT_FAILED;
334 }
335 wifiCountryCode = tempWifiCountryCode;
336 WIFI_LOGI("get wifi country code by cache success, code=%{public}s", wifiCountryCode.c_str());
337 return WIFI_OPT_SUCCESS;
338 }
339
GetWifiCountryCodeByDefaultRegion(std::string & wifiCountryCode)340 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByDefaultRegion(std::string &wifiCountryCode)
341 {
342 char defaultRegion[DEFAULT_REGION_SIZE] = {0};
343 int errorCode = GetParamValue(DEFAULT_REGION_KEY,
344 DEFAULT_REGION, defaultRegion, DEFAULT_REGION_SIZE);
345 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE) {
346 WIFI_LOGI("get wifi country code by default region fail, errorCode=%{public}d", errorCode);
347 return WIFI_OPT_FAILED;
348 }
349 if (!IsValidCountryCode(defaultRegion)) {
350 WIFI_LOGI("get wifi country code by default region fail, code invalid, code=%{public}s", defaultRegion);
351 return WIFI_OPT_FAILED;
352 }
353 wifiCountryCode = defaultRegion;
354 WIFI_LOGI("get wifi country code by default region success, code=%{public}s", wifiCountryCode.c_str());
355 return WIFI_OPT_SUCCESS;
356 }
357
GetWifiCountryCodeByDefault(std::string & wifiCountryCode)358 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByDefault(std::string &wifiCountryCode)
359 {
360 wifiCountryCode = DEFAULT_WIFI_COUNTRY_CODE;
361 WIFI_LOGI("get wifi country code by default success, use default code=%{public}s",
362 DEFAULT_WIFI_COUNTRY_CODE);
363 return WIFI_OPT_SUCCESS;
364 }
365 }
366 }