• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }