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 #include "uri.h"
22 #include "wifi_country_code_manager.h"
23 #include "wifi_global_func.h"
24 #include "wifi_logger.h"
25 #include "wifi_msg.h"
26 #include "wifi_config_center.h"
27 #include "wifi_common_util.h"
28
29 namespace OHOS {
30 namespace Wifi {
31 DEFINE_WIFILOG_LABEL("WifiCountryCodePolicy");
32 const int WIFI_COUNTRY_CODE_REGION_SIZE = 5;
WifiCountryCodePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)33 WifiCountryCodePolicy::WifiCountryCodePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)
34 {
35 CreatePolicy(wifiCountryCodePolicyConf);
36 }
37
CreatePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)38 void WifiCountryCodePolicy::CreatePolicy(std::bitset<WIFI_COUNTRY_CODE_POLICE_DEF_LEN> wifiCountryCodePolicyConf)
39 {
40 WIFI_LOGI("create wifi country code policy");
41 m_policyList.emplace_back(
42 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByFactory(wifiCountryCode); });
43 if (wifiCountryCodePolicyConf[FEATURE_MCC]) {
44 m_policyList.emplace_back(
45 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByMcc(wifiCountryCode); });
46 }
47 if (wifiCountryCodePolicyConf[FEATURE_RCV_AP_CONNECTED]) {
48 m_policyList.emplace_back(
49 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByAP(wifiCountryCode); });
50 }
51 if (wifiCountryCodePolicyConf[FEATURE_RCV_SCAN_RESLUT]) {
52 m_policyList.emplace_back(
53 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByScanResult(wifiCountryCode); });
54 }
55 if (wifiCountryCodePolicyConf[FEATURE_USE_REGION]) {
56 m_policyList.emplace_back(
57 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByRegion(wifiCountryCode); });
58 }
59 if (wifiCountryCodePolicyConf[FEATURE_USE_ZZ]) {
60 m_policyList.emplace_back(
61 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByDefaultZZ(wifiCountryCode); });
62 }
63 m_policyList.emplace_back(
64 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByCache(wifiCountryCode); });
65 m_policyList.emplace_back(
66 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByDefaultRegion(wifiCountryCode); });
67 m_policyList.emplace_back(
68 [this](std::string &wifiCountryCode) { return this->GetWifiCountryCodeByDefault(wifiCountryCode); });
69 }
70
CalculateWifiCountryCode(std::string & wifiCountryCode)71 ErrCode WifiCountryCodePolicy::CalculateWifiCountryCode(std::string &wifiCountryCode)
72 {
73 for (const auto &policy : m_policyList) {
74 if (policy(wifiCountryCode) == WIFI_OPT_SUCCESS) {
75 return WIFI_OPT_SUCCESS;
76 }
77 }
78 return WIFI_OPT_FAILED;
79 }
80
GetWifiCountryCodeByFactory(std::string & wifiCountryCode)81 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByFactory(std::string &wifiCountryCode)
82 {
83 char roRunModeValue[WIFI_COUNTRY_CODE_RUN_MODE_SIZE] = {0};
84 int errorCode = GetParamValue(WIFI_COUNTRY_CODE_RUN_MODE, DEFAULT_RO_RUN_MODE, roRunModeValue,
85 WIFI_COUNTRY_CODE_RUN_MODE_SIZE);
86 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE || strcasecmp(FACTORY_RO_RUN_MODE, roRunModeValue) != 0) {
87 WIFI_LOGI("wifi country code factory mode does not take effect or fail, ret=%{public}d, "
88 "runMode=%{public}s", errorCode, roRunModeValue);
89 return WIFI_OPT_FAILED;
90 }
91 char factoryWifiCountryCodeValue[FACTORY_WIFI_COUNTRY_CODE_SIZE] = {0};
92 errorCode = GetParamValue(FACTORY_WIFI_COUNTRY_CODE, DEFAULT_WIFI_COUNTRY_CODE,
93 factoryWifiCountryCodeValue, FACTORY_WIFI_COUNTRY_CODE_SIZE);
94 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE) {
95 WIFI_LOGI("get wifi country code by factory fail, errorCode=%{public}d", errorCode);
96 return WIFI_OPT_FAILED;
97 }
98 if (!IsValidCountryCode(factoryWifiCountryCodeValue)) {
99 WIFI_LOGI("get wifi country code by factory fail, code invalid, code=%{public}s",
100 factoryWifiCountryCodeValue);
101 return WIFI_OPT_FAILED;
102 }
103 wifiCountryCode = factoryWifiCountryCodeValue;
104 WIFI_LOGI("get wifi country code by factory success, code=%{public}s", wifiCountryCode.c_str());
105 return WIFI_OPT_SUCCESS;
106 }
107
GetWifiCountryCodeByMcc(std::string & wifiCountryCode)108 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByMcc(std::string &wifiCountryCode)
109 {
110 // get cached plmn
111 char cachedPlmn[OPERATOR_NUMERIC_SIZE] = {0};
112 int errorCode = GetParamValue(OPERATOR_NUMERIC_KEY, DEFAULT_OPERATOR_NUMERIC, cachedPlmn, OPERATOR_NUMERIC_SIZE);
113 if (errorCode <= SYSTEM_PARAMETER_ERROR_CODE || strcasecmp(DEFAULT_OPERATOR_NUMERIC, cachedPlmn) == 0) {
114 WIFI_LOGE("get wifi country code by cached mcc fail, ret=%{public}d, cachedPlmn=%{public}s",
115 errorCode, cachedPlmn);
116 return WIFI_OPT_FAILED;
117 }
118 std::string cachedPlmnStr(cachedPlmn);
119 std::string cacheMccStr = cachedPlmnStr.substr(PLMN_SUBSTR_LEFT, PLMN_SUBSTR_RIGHT);
120 int integerCachedMcc = CheckDataLegal(cacheMccStr);
121 if (ConvertMncToIso(integerCachedMcc, wifiCountryCode) != true) {
122 WIFI_LOGE("get wifi country code by cached mcc fail, cached plmn invalid, mcc=%{public}d", integerCachedMcc);
123 return WIFI_OPT_FAILED;
124 }
125
126 // get dynamic plmn
127 std::string dynamicPlmn;
128 #ifdef TELEPHONE_CORE_SERVICE_ENABLE
129 dynamicPlmn = Str16ToStr8(Telephony::CoreServiceClient::GetInstance().GetOperatorNumeric(SLOT_ID));
130 #endif
131 if (dynamicPlmn.empty() || dynamicPlmn.length() < PLMN_LEN) {
132 WIFI_LOGI("get wifi country code by dynamic mcc fail, plmn invalid, plmn=%{public}s, use cached plmn, "
133 "cache code=%{public}s", dynamicPlmn.c_str(), wifiCountryCode.c_str());
134 return WIFI_OPT_SUCCESS;
135 }
136 std::string mccStr = dynamicPlmn.substr(PLMN_SUBSTR_LEFT, PLMN_SUBSTR_RIGHT);
137 int integerMcc = CheckDataLegal(mccStr);
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::lock_guard<std::mutex> guard(countryCodeFromScanResult);
175 std::vector<WifiScanInfo> results;
176 WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(results);
177 if (results.size() == 0) {
178 WIFI_LOGI("get scanResult size is 0");
179 return WIFI_OPT_FAILED;
180 }
181 std::vector<std::string> bssidVector;
182 for (auto &scanInfo : results) {
183 std::string tempWifiCountryCode;
184 ErrCode errorCode = ParseCountryCodeElement(scanInfo.infoElems, tempWifiCountryCode);
185 if (errorCode == WIFI_OPT_FAILED || scanInfo.bssid.empty() || tempWifiCountryCode.empty()) {
186 continue;
187 }
188 StrToUpper(tempWifiCountryCode);
189 m_bssidAndCountryCodeMap.insert_or_assign(scanInfo.bssid, tempWifiCountryCode);
190 bssidVector.push_back(scanInfo.bssid);
191 }
192 m_allBssidVector.push_back(bssidVector);
193 if (m_allBssidVector.size() > MAX_SCAN_SAVED_SIZE) {
194 for (const std::string &bssid : m_allBssidVector[BSSID_VECTOR_INDEX_ZERO]) {
195 if (!IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_ONE], bssid) &&
196 !IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_TWO], bssid) &&
197 !IsContainBssid(m_allBssidVector[BSSID_VECTOR_INDEX_THREE], bssid)) {
198 m_bssidAndCountryCodeMap.erase(bssid); // remove the ap that have not been scanned recently
199 }
200 }
201 m_allBssidVector.erase(m_allBssidVector.begin());
202 }
203 return FindLargestCountCountryCode(wifiCountryCode);
204 }
205
FindLargestCountCountryCode(std::string & wifiCountryCode)206 ErrCode WifiCountryCodePolicy::FindLargestCountCountryCode(std::string &wifiCountryCode)
207 {
208 std::map<std::string, int> codeCount; // counting the number of different country codes
209 for (const auto &info : m_bssidAndCountryCodeMap) {
210 codeCount.insert_or_assign(info.second, codeCount[info.second] + 1);
211 }
212 std::vector<std::pair<std::string, int>> sortCode(codeCount.begin(), codeCount.end());
213 sort(sortCode.begin(), sortCode.end(), [](const std::pair<std::string, int> &a,
214 const std::pair<std::string, int> &b) {
215 return a.second > b.second;
216 });
217 if (sortCode.size() == 0) {
218 WIFI_LOGI("country code count is zero");
219 return WIFI_OPT_FAILED;
220 }
221 if (sortCode.size() == 1) {
222 std::pair<std::string, int> oneCode = sortCode[0];
223 wifiCountryCode = oneCode.first;
224 WIFI_LOGD("only one country, code=%{public}s", wifiCountryCode.c_str());
225 return WIFI_OPT_SUCCESS;
226 }
227 std::pair<std::string, int> firstCode = sortCode[0];
228 std::pair<std::string, int> secondCode = sortCode[1];
229 if (firstCode.second == secondCode.second) {
230 WIFI_LOGI("contains two country codes with the same count and the largest count, unable to make decisions,"
231 " code=%{public}s|%{public}s, count=%{public}d",
232 firstCode.first.c_str(), secondCode.first.c_str(), firstCode.second);
233 return WIFI_OPT_FAILED;
234 }
235 wifiCountryCode = firstCode.first;
236 WIFI_LOGI("largest num of country code=%{public}s", wifiCountryCode.c_str());
237 return WIFI_OPT_SUCCESS;
238 }
239
ParseCountryCodeElement(const std::vector<WifiInfoElem> & infoElems,std::string & wifiCountryCode)240 ErrCode WifiCountryCodePolicy::ParseCountryCodeElement(
241 const std::vector<WifiInfoElem> &infoElems, std::string &wifiCountryCode)
242 {
243 if (infoElems.empty()) {
244 return WIFI_OPT_FAILED;
245 }
246 for (const auto &ie : infoElems) {
247 if (ie.id != COUNTRY_CODE_EID || ie.content.size() < WIFI_COUNTRY_CODE_LEN) {
248 continue;
249 }
250 std::string tempWifiCountryCode;
251 for (int i = 0 ; i < WIFI_COUNTRY_CODE_LEN; i++) {
252 tempWifiCountryCode.push_back(ie.content[i]);
253 }
254 if (!IsValidCountryCode(tempWifiCountryCode)) {
255 continue;
256 }
257 wifiCountryCode = tempWifiCountryCode;
258 return WIFI_OPT_SUCCESS;
259 }
260 return WIFI_OPT_FAILED;
261 }
262
GetWifiCountryCodeByAP(std::string & wifiCountryCode)263 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByAP(std::string &wifiCountryCode)
264 {
265 WifiLinkedInfo result;
266 WifiConfigCenter::GetInstance().GetLinkedInfo(result);
267 if (static_cast<int>(OHOS::Wifi::ConnState::CONNECTED) != result.connState) {
268 return WIFI_OPT_FAILED;
269 }
270 std::vector<WifiScanInfo> scanResults;
271 WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(scanResults);
272 if (scanResults.empty()) {
273 return WIFI_OPT_FAILED;
274 }
275 for (auto &info : scanResults) {
276 if (strcasecmp(info.bssid.c_str(), result.bssid.c_str()) == 0 &&
277 ParseCountryCodeElement(info.infoElems, wifiCountryCode) == WIFI_OPT_SUCCESS) {
278 WIFI_LOGI("get wifi country code by ap success, code=%{public}s", wifiCountryCode.c_str());
279 return WIFI_OPT_SUCCESS;
280 }
281 }
282 WIFI_LOGI("get wifi country code by ap fail, the country code of the AP is incorrect or empty");
283 return WIFI_OPT_FAILED;
284 }
285
GetWifiCountryCodeByScanResult(std::string & wifiCountryCode)286 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByScanResult(std::string &wifiCountryCode)
287 {
288 // if wifi state is not ENABLED, do not obtain the country code from the scan results
289 if (WifiConfigCenter::GetInstance().GetWifiState(SLOT_ID) != static_cast<int>(WifiState::ENABLED) ||
290 m_wifiCountryCodeFromScanResults.empty()) {
291 WIFI_LOGI("get wifi country code by scan result fail, result empty");
292 return WIFI_OPT_FAILED;
293 }
294 wifiCountryCode = m_wifiCountryCodeFromScanResults;
295 WIFI_LOGI("get wifi country code by scan result success, code=%{public}s", wifiCountryCode.c_str());
296 return WIFI_OPT_SUCCESS;
297 }
298
GetWifiCountryCodeByRegion(std::string & wifiCountryCode)299 ErrCode WifiCountryCodePolicy::GetWifiCountryCodeByRegion(std::string &wifiCountryCode)
300 {
301 // the user selects an area in settings
302 std::string tempWifiCountryCode;
303 WifiCountryCodeIntlUtils wifiCountryCodeIntlUtils;
304 tempWifiCountryCode = wifiCountryCodeIntlUtils.GetSystemRegion();
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 void* WifiCountryCodeIntlUtils::libHandle_ = nullptr;
367
GetSystemRegion()368 std::string WifiCountryCodeIntlUtils::GetSystemRegion()
369 {
370 std::string region = "";
371 using GetSystemRegionFunc = void (*)(char *, int);
372 GetSystemRegionFunc getSystemRegion = nullptr;
373 getSystemRegion = reinterpret_cast<GetSystemRegionFunc>(wifiLibraryUtils_.GetFunction("GetSystemRegion"));
374 if (getSystemRegion == nullptr) {
375 WIFI_LOGE("GetSystemRegion function is nullptr");
376 return region;
377 }
378 char regionChar[WIFI_COUNTRY_CODE_REGION_SIZE] = {0};
379 getSystemRegion(regionChar, WIFI_COUNTRY_CODE_REGION_SIZE);
380 region = regionChar;
381 return region;
382 }
383 }
384 }