• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sstream>
17 #include "network_selection_manager.h"
18 #include "wifi_settings.h"
19 #include "wifi_logger.h"
20 #include "network_selection_utils.h"
21 #include "wifi_common_util.h"
22 #include "wifi_hisysevent.h"
23 #include "wifi_sensor_scene.h"
24 #include "wifi_channel_helper.h"
25 #include "wifi_service_manager.h"
26 #include "wifi_config_center.h"
27 
28 namespace OHOS::Wifi {
29 DEFINE_WIFILOG_LABEL("networkSelectionManager")
30 
31 const int OUTDOOR_NETWORK_SELECT_THRES = 3;
32 
NetworkSelectionManager()33 NetworkSelectionManager::NetworkSelectionManager()
34 {
35     pNetworkSelectorFactory = std::make_unique<NetworkSelectorFactory>();
36 }
37 
SelectNetworkWithSsid(WifiDeviceConfig & deviceConfig,std::string & autoSelectBssid)38 void NetworkSelectionManager::SelectNetworkWithSsid(WifiDeviceConfig& deviceConfig, std::string& autoSelectBssid)
39 {
40     WIFI_LOGI("Enter SelectNetworkWithSsid.");
41     std::vector<WifiScanInfo> wifiScanInfoList;
42     WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(wifiScanInfoList);
43     std::vector<InterScanInfo> interScanInfoList;
44     for (auto &wifiScanInfo : wifiScanInfoList) {
45         std::string deviceKeyMgmt;
46         wifiScanInfo.GetDeviceMgmt(deviceKeyMgmt);
47         if (wifiScanInfo.ssid == deviceConfig.ssid &&
48             WifiSettings::GetInstance().InKeyMgmtBitset(deviceConfig, deviceKeyMgmt)) {
49             InterScanInfo interScanInfo;
50             ConvertScanInfo(wifiScanInfo, interScanInfo);
51             interScanInfoList.push_back(interScanInfo);
52         }
53     }
54     WIFI_LOGI("select scanInfo size: %{public}zu", interScanInfoList.size());
55     NetworkSelectionResult networkSelectionResult;
56     SelectNetwork(networkSelectionResult, NetworkSelectType::USER_CONNECT, interScanInfoList);
57     autoSelectBssid = networkSelectionResult.interScanInfo.bssid;
58 }
59 
ConvertScanInfo(WifiScanInfo & wifiScanInfo,InterScanInfo & interScanInfo)60 void NetworkSelectionManager::ConvertScanInfo(WifiScanInfo &wifiScanInfo, InterScanInfo &interScanInfo)
61 {
62     interScanInfo.bssid = wifiScanInfo.bssid;
63     interScanInfo.ssid = wifiScanInfo.ssid;
64     interScanInfo.oriSsid = wifiScanInfo.oriSsid;
65     interScanInfo.capabilities = wifiScanInfo.capabilities;
66     interScanInfo.frequency = wifiScanInfo.frequency;
67     interScanInfo.channelWidth = wifiScanInfo.channelWidth;
68     interScanInfo.centerFrequency0 = wifiScanInfo.centerFrequency0;
69     interScanInfo.centerFrequency1 = wifiScanInfo.centerFrequency1;
70     interScanInfo.rssi = wifiScanInfo.rssi;
71     interScanInfo.securityType = wifiScanInfo.securityType;
72     interScanInfo.infoElems = wifiScanInfo.infoElems;
73     interScanInfo.features = wifiScanInfo.features;
74     interScanInfo.timestamp = wifiScanInfo.timestamp;
75     interScanInfo.band = wifiScanInfo.band;
76     interScanInfo.isHiLinkNetwork = wifiScanInfo.isHiLinkNetwork;
77     interScanInfo.supportedWifiCategory = wifiScanInfo.supportedWifiCategory;
78 }
79 
SelectNetwork(NetworkSelectionResult & networkSelectionResult,NetworkSelectType type,const std::vector<InterScanInfo> & scanInfos)80 bool NetworkSelectionManager::SelectNetwork(NetworkSelectionResult &networkSelectionResult,
81                                             NetworkSelectType type,
82                                             const std::vector<InterScanInfo> &scanInfos)
83 {
84     if (scanInfos.empty()) {
85         WIFI_LOGI("scanInfos is empty, ignore this selection");
86         return false;
87     }
88 
89     /* networkCandidates must be declared before networkSelector,
90      * so it can be accessed in the destruct of networkSelector and wifiFilter */
91     std::vector<NetworkSelection::NetworkCandidate> networkCandidates;
92     auto networkSelectorOptional = pNetworkSelectorFactory->GetNetworkSelector(type);
93     if (!(networkSelectorOptional.has_value())) {
94         WIFI_LOGE("Get NetworkSelector failed for type %{public}d", static_cast<int>(type));
95         return false;
96     }
97     auto &networkSelector = networkSelectorOptional.value();
98     WIFI_LOGI("NetworkSelector: %{public}s", networkSelector->GetNetworkSelectorMsg().c_str());
99 
100     /* Get the device config for each scanInfo, then create networkCandidate and put it into networkCandidates */
101     GetAllDeviceConfigs(networkCandidates, scanInfos);
102     bool isSavedNetEmpty = false;
103     std::string savedResult = GetSavedNetInfoForChr(networkCandidates, isSavedNetEmpty);
104 
105     /* Traverse networkCandidates and reserve qualified networkCandidate */
106     TryNominate(networkCandidates, networkSelector);
107 
108     std::string filteredReason = GetFilteredReasonForChr(networkCandidates);
109 
110     /* Get best networkCandidate from the reserved networkCandidates */
111     std::vector<NetworkSelection::NetworkCandidate *> bestNetworkCandidates;
112     networkSelector->GetBestCandidates(bestNetworkCandidates);
113 
114     std::string selectedInfo;
115     if (bestNetworkCandidates.empty()) {
116         if (!isSavedNetEmpty) {
117             WriteAutoSelectHiSysEvent(static_cast<int>(type), selectedInfo, filteredReason, savedResult);
118         }
119         return false;
120     } else {
121         selectedInfo = GetSelectedInfoForChr(bestNetworkCandidates.at(0));
122         WriteAutoSelectHiSysEvent(static_cast<int>(type), selectedInfo, filteredReason, savedResult);
123     }
124 
125     /* Determine whether to select bestNetworkCandidates in outdoor scene */
126     IodStatisticInfo iodStatisticInfo;
127     iodStatisticInfo.outdoorAutoSelectCnt++;
128     if (IsOutdoorFilter(bestNetworkCandidates.at(0))) {
129         WIFI_LOGI("bestNetworkCandidates do not satisfy outdoor select condition");
130         iodStatisticInfo.outdoorFilterCnt++;
131         WriteIodHiSysEvent(iodStatisticInfo);
132         return false;
133     }
134     WriteIodHiSysEvent(iodStatisticInfo);
135 
136     /* if bestNetworkCandidates is not empty, assign the value of first bestNetworkCandidate
137      * to the network selection result, and return true which means the network selection is successful */
138     networkSelectionResult.wifiDeviceConfig = bestNetworkCandidates.at(0)->wifiDeviceConfig;
139     networkSelectionResult.interScanInfo = bestNetworkCandidates.at(0)->interScanInfo;
140     return true;
141 }
142 
GetAllDeviceConfigs(std::vector<NetworkSelection::NetworkCandidate> & networkCandidates,const std::vector<InterScanInfo> & scanInfos)143 void NetworkSelectionManager::GetAllDeviceConfigs(std::vector<NetworkSelection::NetworkCandidate> &networkCandidates,
144                                                   const std::vector<InterScanInfo> &scanInfos)
145 {
146     std::map<int, std::size_t> wifiDeviceConfigs;
147     std::map<int, std::size_t> wifiCandidateConfigs;
148     for (auto &scanInfo : scanInfos) {
149         auto& networkCandidate = networkCandidates.emplace_back(scanInfo);
150         std::string deviceKeyMgmt;
151         scanInfo.GetDeviceMgmt(deviceKeyMgmt);
152         WifiSettings::GetInstance().GetDeviceConfig(scanInfo.ssid, deviceKeyMgmt, networkCandidate.wifiDeviceConfig);
153 
154         // save the indexes of saved network candidate in networkCandidates;
155         if (networkCandidates.back().wifiDeviceConfig.networkId != INVALID_NETWORK_ID) {
156             wifiDeviceConfigs.insert({networkCandidate.wifiDeviceConfig.networkId, networkCandidates.size() - 1});
157             WifiSettings::GetInstance().SetNetworkCandidateScanResult(networkCandidate.wifiDeviceConfig.networkId);
158             continue;
159         }
160 
161         // add suggesion network
162         WifiSettings::GetInstance().GetCandidateConfigWithoutUid(scanInfo.ssid, deviceKeyMgmt,
163             networkCandidate.wifiDeviceConfig);
164         if (networkCandidates.back().wifiDeviceConfig.networkId != INVALID_NETWORK_ID &&
165             networkCandidates.back().wifiDeviceConfig.uid != WIFI_INVALID_UID &&
166             networkCandidates.back().wifiDeviceConfig.isShared == false) {
167             wifiCandidateConfigs.insert({networkCandidate.wifiDeviceConfig.networkId, networkCandidates.size() - 1});
168         }
169     }
170 
171     std::stringstream wifiDevicesInfo;
172     for (auto &pair: wifiDeviceConfigs) {
173         if (wifiDevicesInfo.rdbuf() ->in_avail() != 0) {
174             wifiDevicesInfo << ",";
175         }
176         wifiDevicesInfo << "\"" << pair.first << "_" <<
177             SsidAnonymize(networkCandidates.at(pair.second).wifiDeviceConfig.ssid) << "_" <<
178             networkCandidates.at(pair.second).wifiDeviceConfig.keyMgmt << "\"";
179     }
180 
181     std::stringstream wifiCandidateInfos;
182     for (auto &pair: wifiCandidateConfigs) {
183         if (wifiCandidateInfos.rdbuf() ->in_avail() != 0) {
184             wifiCandidateInfos << ",";
185         }
186         wifiCandidateInfos << "\"" << pair.first << "_" <<
187             SsidAnonymize(networkCandidates.at(pair.second).wifiDeviceConfig.ssid) << "\"";
188     }
189     WIFI_LOGI("Find savedNetworks in scanInfos: [%{public}s]\n"
190         "Find suggestion networks in scanInfos: [%{public}s]",
191         wifiDevicesInfo.str().c_str(), wifiCandidateInfos.str().c_str());
192 }
193 
TryNominate(std::vector<NetworkSelection::NetworkCandidate> & networkCandidates,const std::unique_ptr<NetworkSelection::INetworkSelector> & networkSelector)194 void NetworkSelectionManager::TryNominate(std::vector<NetworkSelection::NetworkCandidate> &networkCandidates,
195                                           const std::unique_ptr<NetworkSelection::INetworkSelector> &networkSelector)
196 {
197     std::for_each(networkCandidates.begin(), networkCandidates.end(), [&networkSelector](auto &networkCandidate) {
198         networkSelector->TryNominate(networkCandidate);
199     });
200 }
201 
GetSavedNetInfoForChr(std::vector<NetworkSelection::NetworkCandidate> & networkCandidates,bool & isSavedNetEmpty)202 std::string NetworkSelectionManager::GetSavedNetInfoForChr(
203     std::vector<NetworkSelection::NetworkCandidate> &networkCandidates, bool &isSavedNetEmpty)
204 {
205     std::map<int, NetworkSelection::NetworkCandidate> savedCandidates;
206     for (size_t i = 0; i < networkCandidates.size(); i++) {
207         if (networkCandidates.at(i).wifiDeviceConfig.networkId == INVALID_NETWORK_ID) {
208             continue;
209         }
210         savedCandidates.insert({networkCandidates.at(i).wifiDeviceConfig.networkId,
211             networkCandidates.at(i)});
212     }
213     if (savedCandidates.empty()) {
214         isSavedNetEmpty = true;
215     }
216     std::string savedResult;
217     savedResult += "[";
218     for (auto pair : savedCandidates) {
219         savedResult += "[";
220         savedResult += std::to_string(pair.first);
221         savedResult += "_";
222         savedResult += SsidAnonymize(pair.second.wifiDeviceConfig.ssid);
223         savedResult += "_";
224         savedResult += pair.second.wifiDeviceConfig.keyMgmt;
225         savedResult += "]";
226     }
227     savedResult += "]";
228     return savedResult;
229 }
230 
GetFilteredReasonForChr(std::vector<NetworkSelection::NetworkCandidate> & networkCandidates)231 std::string NetworkSelectionManager::GetFilteredReasonForChr(
232     std::vector<NetworkSelection::NetworkCandidate> &networkCandidates)
233 {
234     std::string filteredReasons;
235     filteredReasons += "[";
236     for (size_t i = 0; i < networkCandidates.size(); i++) {
237         if (networkCandidates.at(i).wifiDeviceConfig.networkId == INVALID_NETWORK_ID) {
238             continue;
239         }
240         std::map<std::string, std::set<NetworkSelection::FiltedReason,
241             NetworkSelection::FiltedReasonComparator, std::allocator<NetworkSelection::FiltedReason>>> filtedReason;
242         filtedReason = networkCandidates.at(i).filtedReason;
243         if (filtedReason.size() == 0) {
244             continue;
245         }
246         filteredReasons += "[";
247         for (const auto& pair : filtedReason) {
248             std::string filterName = pair.first;
249             filteredReasons += filterName;
250             filteredReasons += "_";
251             filteredReasons += networkCandidates.at(i).ToString(filterName);
252         }
253         filteredReasons += "]";
254         if (i < networkCandidates.size() - 1) {
255             filteredReasons += ", ";
256         }
257     }
258     filteredReasons += "]";
259     return filteredReasons;
260 }
261 
GetSelectedInfoForChr(NetworkSelection::NetworkCandidate * networkCandidate)262 std::string NetworkSelectionManager::GetSelectedInfoForChr(NetworkSelection::NetworkCandidate *networkCandidate)
263 {
264     std::string selectedInfo;
265     WifiDeviceConfig selectedConfig;
266     selectedConfig = networkCandidate->wifiDeviceConfig;
267     selectedInfo += std::to_string(selectedConfig.networkId);
268     selectedInfo += "_";
269     selectedInfo += SsidAnonymize(selectedConfig.ssid);
270     selectedInfo += "_";
271     selectedInfo += MacAnonymize(selectedConfig.bssid);
272     selectedInfo += "_";
273     selectedInfo += selectedConfig.keyMgmt;
274     selectedInfo += "_";
275     selectedInfo += std::to_string(networkCandidate->interScanInfo.frequency);
276     selectedInfo += "_";
277     selectedInfo += std::to_string(networkCandidate->interScanInfo.rssi);
278     return selectedInfo;
279 }
280 
IsOutdoorFilter(NetworkSelection::NetworkCandidate * networkCandidate)281 bool NetworkSelectionManager::IsOutdoorFilter(NetworkSelection::NetworkCandidate *networkCandidate)
282 {
283     std::lock_guard<std::mutex> lock(rssiCntMutex_);
284     if (!WifiSensorScene::GetInstance().IsOutdoorScene()) {
285         WIFI_LOGI("IsOutdoorFilter indoor scene do not filter");
286         rssiCntMap_.clear();
287         return false;
288     }
289     if ((WifiChannelHelper::GetInstance().IsValid5GHz(networkCandidate->interScanInfo.frequency) &&
290             networkCandidate->interScanInfo.rssi >= RSSI_LEVEL_4_5G) ||
291         (WifiChannelHelper::GetInstance().IsValid24GHz(networkCandidate->interScanInfo.frequency) &&
292             networkCandidate->interScanInfo.rssi >= RSSI_LEVEL_4_2G)) {
293         WIFI_LOGI("IsOutdoorFilter outdoor strong signal do not filter");
294         rssiCntMap_.clear();
295         return false;
296     }
297     if ((WifiChannelHelper::GetInstance().IsValid5GHz(networkCandidate->interScanInfo.frequency) &&
298             networkCandidate->interScanInfo.rssi < RSSI_LEVEL_3_5G) ||
299         (WifiChannelHelper::GetInstance().IsValid24GHz(networkCandidate->interScanInfo.frequency) &&
300             networkCandidate->interScanInfo.rssi < RSSI_LEVEL_3_2G)) {
301         rssiCntMap_.clear();
302         return true;
303     }
304     if (rssiCntMap_[networkCandidate->interScanInfo.bssid] < OUTDOOR_NETWORK_SELECT_THRES) {
305         rssiCntMap_[networkCandidate->interScanInfo.bssid]++;
306         int instId = 0;
307         IScanService *pScanService = WifiServiceManager::GetInstance().GetScanServiceInst(instId);
308         if (pScanService == nullptr || pScanService->ResetScanInterval() != WIFI_OPT_SUCCESS) {
309             WIFI_LOGE("IsOutdoorFilter ResetScanInterval failed");
310             rssiCntMap_.clear();
311             return false;
312         }
313         return true;
314     }
315     WIFI_LOGI("IsOutdoorFilter signal satisfy outdoor select condition");
316     rssiCntMap_.clear();
317     return false;
318 }
319 }