1 /*
2 * Copyright (C) 2021 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 #include "sta_auto_connect_service.h"
16 #include "wifi_logger.h"
17 #include "wifi_sta_hal_interface.h"
18 #include "wifi_config_center.h"
19 #include "wifi_common_util.h"
20 #include "block_connect_service.h"
21
22 DEFINE_WIFILOG_LABEL("StaAutoConnectService");
23
24 namespace OHOS {
25 namespace Wifi {
StaAutoConnectService(StaStateMachine * staStateMachine,int instId)26 StaAutoConnectService::StaAutoConnectService(StaStateMachine *staStateMachine, int instId)
27 : pStaStateMachine(staStateMachine),
28 pSavedDeviceAppraisal(nullptr),
29 firmwareRoamFlag(true),
30 maxBlockedBssidNum(BLOCKLIST_INVALID_SIZE),
31 selectDeviceLastTime(0),
32 pAppraisals {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
33 m_instId(instId)
34 {}
35
~StaAutoConnectService()36 StaAutoConnectService::~StaAutoConnectService()
37 {
38 WIFI_LOGI("Enter ~StaAutoConnectService.\n");
39 if (pSavedDeviceAppraisal != nullptr) {
40 delete pSavedDeviceAppraisal;
41 pSavedDeviceAppraisal = nullptr;
42 }
43 }
44
InitAutoConnectService()45 ErrCode StaAutoConnectService::InitAutoConnectService()
46 {
47 WIFI_LOGI("Enter InitAutoConnectService.\n");
48
49 if (ObtainRoamCapFromFirmware()) {
50 WIFI_LOGI("Succeeded in obtaining firmware roaming information.\n");
51 }
52 SyncBlockedSsidFirmware();
53
54 pSavedDeviceAppraisal = new (std::nothrow) StaSavedDeviceAppraisal(firmwareRoamFlag);
55 if (pSavedDeviceAppraisal == nullptr) {
56 WIFI_LOGE("savedDeviceAppraisal is null\n");
57 return WIFI_OPT_FAILED;
58 }
59 pNetworkSelectionManager = std::make_unique<NetworkSelectionManager>();
60 int savedPriority = WifiSettings::GetInstance().GetSavedDeviceAppraisalPriority(m_instId);
61 if (RegisterDeviceAppraisal(pSavedDeviceAppraisal, savedPriority)) {
62 WIFI_LOGI("RegisterSavedDeviceAppraisal succeeded.\n");
63 }
64 return WIFI_OPT_SUCCESS;
65 }
66
SetAutoConnectStateCallback(const std::vector<StaServiceCallback> & callbacks)67 void StaAutoConnectService::SetAutoConnectStateCallback(const std::vector<StaServiceCallback> &callbacks)
68 {
69 WIFI_LOGI("Enter SetAutoConnectStateCallback.\n");
70 mStaCallbacks = callbacks;
71 }
72
OnScanInfosReadyHandler(const std::vector<InterScanInfo> & scanInfos)73 void StaAutoConnectService::OnScanInfosReadyHandler(const std::vector<InterScanInfo> &scanInfos)
74 {
75 WIFI_LOGI("Enter OnScanInfosReadyHandler.\n");
76 ClearOvertimeBlockedBssid(); /* Refreshing the BSSID Blocklist */
77
78 WifiLinkedInfo info;
79 WifiConfigCenter::GetInstance().GetLinkedInfo(info, m_instId);
80 if (info.supplicantState == SupplicantState::ASSOCIATING ||
81 info.supplicantState == SupplicantState::ASSOCIATED ||
82 info.supplicantState == SupplicantState::AUTHENTICATING ||
83 info.supplicantState == SupplicantState::FOUR_WAY_HANDSHAKE ||
84 info.supplicantState == SupplicantState::GROUP_HANDSHAKE) {
85 WIFI_LOGE("Supplicant is under transient state.\n");
86 return;
87 }
88
89 if (info.connState == ConnState::CONNECTED) {
90 ClearAllBlockedBssids();
91 }
92 std::vector<std::string> blockedBssids;
93 GetBlockedBssids(blockedBssids);
94 if (!AllowAutoSelectDevice(info) || !IsAllowAutoJoin()) {
95 return;
96 }
97 BlockConnectService::GetInstance().UpdateAllNetworkSelectStatus();
98 NetworkSelectionResult networkSelectionResult;
99 if (pNetworkSelectionManager->SelectNetwork(networkSelectionResult, NetworkSelectType::AUTO_CONNECT, scanInfos)) {
100 int networkId = networkSelectionResult.wifiDeviceConfig.networkId;
101 std::string &bssid = networkSelectionResult.interScanInfo.bssid;
102 std::string &ssid = networkSelectionResult.interScanInfo.ssid;
103 WIFI_LOGI("AutoSelectDevice networkId: %{public}d, ssid: %{public}s, bssid: %{public}s.", networkId,
104 SsidAnonymize(ssid).c_str(), MacAnonymize(bssid).c_str());
105 auto message = pStaStateMachine->CreateMessage(WIFI_SVR_CMD_STA_CONNECT_SAVED_NETWORK);
106 message->SetParam1(networkId);
107 message->SetParam2(NETWORK_SELECTED_BY_AUTO);
108 message->AddStringMessageBody(bssid);
109 pStaStateMachine->SendMessage(message);
110 } else {
111 WIFI_LOGI("AutoSelectDevice return fail.");
112 }
113 for (const auto &callBackItem : mStaCallbacks) {
114 if (callBackItem.OnAutoSelectNetworkRes != nullptr) {
115 callBackItem.OnAutoSelectNetworkRes(networkSelectionResult.wifiDeviceConfig.networkId, m_instId);
116 }
117 }
118 }
119
EnableOrDisableBssid(std::string bssid,bool enable,int reason)120 bool StaAutoConnectService::EnableOrDisableBssid(std::string bssid, bool enable, int reason)
121 {
122 WIFI_LOGI("Enter EnableOrDisableBssid.\n");
123 if (bssid.empty()) {
124 WIFI_LOGI("bssid is empty.\n");
125 return false;
126 }
127
128 /* Updating the BSSID Blocklist */
129 if (!AddOrDelBlockedBssids(bssid, enable, reason)) {
130 WIFI_LOGI("The blocklist is not updated.\n");
131 return false;
132 }
133
134 /* The blocklist has been updated, so update the firmware roaming */
135 /* configuration */
136 SyncBlockedSsidFirmware();
137 return true;
138 }
139
AddOrDelBlockedBssids(std::string bssid,bool enable,int reason)140 bool StaAutoConnectService::AddOrDelBlockedBssids(std::string bssid, bool enable, int reason)
141 {
142 std::lock_guard<std::mutex> lock(m_blockBssidMapMutex);
143 WIFI_LOGI("Enter AddOrDelBlockedBssids.\n");
144 if (enable) {
145 if (blockedBssidMap.count(bssid) != 0) {
146 /* Removed the BSSID from the blocklist When the BSSID is enabled. */
147 blockedBssidMap.erase(bssid);
148 return true;
149 }
150 return false;
151 }
152
153 BlockedBssidInfo status;
154 auto iter = blockedBssidMap.find(bssid);
155 if (iter == blockedBssidMap.end()) {
156 blockedBssidMap.emplace(bssid, status);
157 }
158 auto iterator = blockedBssidMap.find(bssid);
159 if (iterator == blockedBssidMap.end()) {
160 return false;
161 }
162 iterator->second.count++;
163 time_t now = time(nullptr);
164 if (now == static_cast<time_t>(-1)) {
165 return false;
166 }
167 iterator->second.blockedTime = static_cast<int>(now);
168 if (!iterator->second.blockedFlag) {
169 if (iterator->second.count >= MAX_BSSID_BLOCKLIST_COUNT ||
170 reason == AP_CANNOT_HANDLE_NEW_STA) {
171 iterator->second.blockedFlag = true;
172 return true;
173 }
174 }
175 return false;
176 }
177
GetBlockedBssids(std::vector<std::string> & blockedBssids)178 void StaAutoConnectService::GetBlockedBssids(std::vector<std::string> &blockedBssids)
179 {
180 std::lock_guard<std::mutex> lock(m_blockBssidMapMutex);
181 for (auto iter = blockedBssidMap.begin(); iter != blockedBssidMap.end(); ++iter) {
182 blockedBssids.push_back(iter->first);
183 }
184 WIFI_LOGD("GetBlockedBssids, blockedBssids count: %{public}d.", (int)blockedBssids.size());
185 return;
186 }
187
ClearAllBlockedBssids()188 void StaAutoConnectService::ClearAllBlockedBssids()
189 {
190 std::lock_guard<std::mutex> lock(m_blockBssidMapMutex);
191 WIFI_LOGI("Enter ClearAllBlockedBssids.\n");
192 blockedBssidMap.clear();
193 return;
194 }
195
ClearOvertimeBlockedBssid()196 void StaAutoConnectService::ClearOvertimeBlockedBssid()
197 {
198 std::lock_guard<std::mutex> lock(m_blockBssidMapMutex);
199 WIFI_LOGI("Enter ClearOvertimeBlockedBssid.\n");
200 if (blockedBssidMap.empty()) {
201 WIFI_LOGI("blockedBssidMap is empty !\n");
202 return;
203 }
204 bool updated = false;
205 auto iter = blockedBssidMap.begin();
206 while (iter != blockedBssidMap.end()) {
207 BlockedBssidInfo status = iter->second;
208 time_t now = time(nullptr);
209 int currentTimeStap = static_cast<int>(now);
210 WIFI_LOGI("blockedFlag:%{public}d, currentTimeStap:%{public}d, blockedTime:%{public}d.\n",
211 status.blockedFlag, currentTimeStap, status.blockedTime);
212 if (status.blockedFlag && ((currentTimeStap - status.blockedTime) >= MAX_BSSID_BLOCKLIST_TIME)) {
213 blockedBssidMap.erase(iter++);
214 updated = true;
215 } else {
216 ++iter;
217 }
218 }
219 if (updated) {
220 SyncBlockedSsidFirmware();
221 }
222 return;
223 }
224
ConnectElectedDevice(WifiDeviceConfig & electedDevice)225 void StaAutoConnectService::ConnectElectedDevice(WifiDeviceConfig &electedDevice)
226 {
227 WIFI_LOGI("Enter ConnectElectedDevice.\n");
228 if (electedDevice.bssid.empty()) {
229 WIFI_LOGE("electedDevice bssid is empty.");
230 return;
231 }
232
233 WifiLinkedInfo currentConnectedNetwork;
234 WifiConfigCenter::GetInstance().GetLinkedInfo(currentConnectedNetwork, m_instId);
235 if (currentConnectedNetwork.connState == ConnState::CONNECTED && electedDevice.networkId == INVALID_NETWORK_ID &&
236 currentConnectedNetwork.ssid == electedDevice.ssid && currentConnectedNetwork.bssid != electedDevice.bssid) {
237 /* Frameworks start roaming only when firmware is not supported */
238 if (!firmwareRoamFlag) {
239 WIFI_LOGI("Roaming connectTo, networkId: %{public}d.\n", electedDevice.networkId);
240 pStaStateMachine->StartRoamToNetwork(electedDevice.bssid);
241 }
242 } else if (currentConnectedNetwork.detailedState == DetailedState::DISCONNECTED ||
243 currentConnectedNetwork.detailedState == DetailedState::CONNECTION_TIMEOUT ||
244 currentConnectedNetwork.detailedState == DetailedState::FAILED ||
245 currentConnectedNetwork.detailedState == DetailedState::PASSWORD_ERROR ||
246 currentConnectedNetwork.detailedState == DetailedState::CONNECTION_FULL ||
247 currentConnectedNetwork.detailedState == DetailedState::CONNECTION_REJECT) {
248 pStaStateMachine->SendMessage(WIFI_SVR_CMD_STA_CONNECT_SAVED_NETWORK,
249 electedDevice.networkId,
250 NETWORK_SELECTED_BY_AUTO);
251 WIFI_LOGI("connectTo save networkId: %{public}d, preShareKey len: %{public}d.\n",
252 electedDevice.networkId, (int)electedDevice.preSharedKey.length());
253 } else {
254 WIFI_LOGE("The current connection status is %{public}d.\n", currentConnectedNetwork.detailedState);
255 }
256 return;
257 }
258
SyncBlockedSsidFirmware()259 void StaAutoConnectService::SyncBlockedSsidFirmware()
260 {
261 WIFI_LOGI("Enter SyncBlockedSsidFirmware.\n");
262 if (!firmwareRoamFlag) {
263 return;
264 }
265 if (maxBlockedBssidNum <= 0) {
266 return;
267 }
268 std::vector<std::string> blockedBssids;
269 GetBlockedBssids(blockedBssids);
270
271 if (static_cast<int>(blockedBssids.size()) > maxBlockedBssidNum) {
272 blockedBssids.resize(maxBlockedBssidNum);
273 }
274
275 if (SetRoamBlockedBssidFirmware(blockedBssids)) {
276 WIFI_LOGE("Set firmware roaming configuration succeeded.\n");
277 } else {
278 WIFI_LOGI("Set firmware roaming configuration failed.\n");
279 }
280 return;
281 }
282
ObtainRoamCapFromFirmware()283 bool StaAutoConnectService::ObtainRoamCapFromFirmware()
284 {
285 WIFI_LOGI("Enter ObtainRoamCapFromFirmware.\n");
286
287 unsigned int capabilities;
288 if (WifiStaHalInterface::GetInstance().GetStaCapabilities(capabilities) == WIFI_HAL_OPT_OK) {
289 if ((capabilities & STA_CAP_ROAMING) == 0) {
290 WIFI_LOGE("Firmware roaming is not supported.\n");
291 return false;
292 }
293 }
294
295 WifiHalRoamCapability capability;
296 if (WifiStaHalInterface::GetInstance().GetRoamingCapabilities(capability) == WIFI_HAL_OPT_OK) {
297 if (capability.maxBlocklistSize > 0) {
298 firmwareRoamFlag = true;
299 maxBlockedBssidNum = capability.maxBlocklistSize;
300 WIFI_LOGI("Get firmware roaming capabilities succeeded.\n");
301 return true;
302 }
303 WIFI_LOGE("Invalid firmware roaming capabilities.\n");
304 }
305
306 WIFI_LOGE("Get firmware roaming capabilities failed.\n");
307 return false;
308 }
309
SetRoamBlockedBssidFirmware(const std::vector<std::string> & blocklistBssids) const310 bool StaAutoConnectService::SetRoamBlockedBssidFirmware(const std::vector<std::string> &blocklistBssids) const
311 {
312 WIFI_LOGI("Enter SetRoamBlockedBssidFirmware.\n");
313 if (!firmwareRoamFlag) {
314 return false;
315 }
316
317 if (blocklistBssids.empty()) {
318 return false;
319 }
320
321 if (static_cast<int>(blocklistBssids.size()) > maxBlockedBssidNum) {
322 return false;
323 }
324
325 WifiHalRoamConfig capability;
326 capability.blocklistBssids = blocklistBssids;
327 if (WifiStaHalInterface::GetInstance().SetRoamConfig(capability) == WIFI_HAL_OPT_OK) {
328 return true;
329 }
330 return false;
331 }
332
RegisterDeviceAppraisal(StaDeviceAppraisal * appraisal,int priority)333 bool StaAutoConnectService::RegisterDeviceAppraisal(StaDeviceAppraisal *appraisal, int priority)
334 {
335 WIFI_LOGI("Enter RegisterDeviceAppraisal.\n");
336 if (priority < 0 || priority >= MIN_APPRAISAL_PRIORITY) {
337 WIFI_LOGE("Out of array range.\n");
338 return false;
339 }
340 if (pAppraisals[priority] != nullptr) {
341 WIFI_LOGE("Appraisals is not empty.\n");
342 return false;
343 }
344 pAppraisals[priority] = appraisal;
345 return true;
346 }
347
AutoSelectDevice(WifiDeviceConfig & electedDevice,const std::vector<InterScanInfo> & scanInfos,std::vector<std::string> & blockedBssids,WifiLinkedInfo & info)348 ErrCode StaAutoConnectService::AutoSelectDevice(WifiDeviceConfig &electedDevice,
349 const std::vector<InterScanInfo> &scanInfos, std::vector<std::string> &blockedBssids, WifiLinkedInfo &info)
350 {
351 WIFI_LOGI("Enter SelectNetwork.\n");
352 if (scanInfos.empty()) {
353 WIFI_LOGE("scanInfo is empty.");
354 return WIFI_OPT_FAILED;
355 }
356
357 /* Whether network selection handover is required */
358 if (!AllowAutoSelectDevice(scanInfos, info)) {
359 WIFI_LOGE("Network switching is not required.\n");
360 return WIFI_OPT_FAILED;
361 }
362
363 std::vector<InterScanInfo> availableScanInfos;
364 /* Filter out unnecessary networks. */
365 GetAvailableScanInfos(availableScanInfos, scanInfos, blockedBssids, info);
366 if (availableScanInfos.empty()) {
367 WIFI_LOGE("No scanInfo available.\n");
368 return WIFI_OPT_FAILED;
369 }
370 /*
371 * Check the registered network appraisal from highest priority to lowest
372 * priority until the selected network
373 */
374 for (auto registeredAppraisal : pAppraisals) {
375 if (registeredAppraisal != nullptr) {
376 ErrCode code = registeredAppraisal->DeviceAppraisals(electedDevice, availableScanInfos, info);
377 if (code == WIFI_OPT_SUCCESS) {
378 time_t now = time(nullptr);
379 selectDeviceLastTime = static_cast<int>(now);
380 WIFI_LOGI("electedDevice generation.\n");
381 return WIFI_OPT_SUCCESS;
382 }
383 }
384 }
385
386 if (RoamingSelection(electedDevice, availableScanInfos, info)) {
387 WIFI_LOGI("Roaming network generation.\n");
388 return WIFI_OPT_SUCCESS;
389 }
390 WIFI_LOGE("No electedDevice.\n");
391 return WIFI_OPT_FAILED;
392 }
393
RoamingSelection(WifiDeviceConfig & electedDevice,std::vector<InterScanInfo> & availableScanInfos,WifiLinkedInfo & info)394 bool StaAutoConnectService::RoamingSelection(
395 WifiDeviceConfig &electedDevice, std::vector<InterScanInfo> &availableScanInfos, WifiLinkedInfo &info)
396 {
397 for (auto scanInfo : availableScanInfos) {
398 if (info.connState == ConnState::CONNECTED && scanInfo.ssid == info.ssid && scanInfo.bssid != info.bssid) {
399 WIFI_LOGD("Discover roaming networks.\n");
400 if (RoamingEncryptionModeCheck(electedDevice, scanInfo, info)) {
401 return true;
402 }
403 }
404 }
405 return false;
406 }
407
RoamingEncryptionModeCheck(WifiDeviceConfig & electedDevice,InterScanInfo scanInfo,WifiLinkedInfo & info)408 bool StaAutoConnectService::RoamingEncryptionModeCheck(
409 WifiDeviceConfig &electedDevice, InterScanInfo scanInfo, WifiLinkedInfo &info)
410 {
411 WifiDeviceConfig network;
412 if (WifiSettings::GetInstance().GetDeviceConfig(scanInfo.ssid, DEVICE_CONFIG_INDEX_SSID, network) == 0) {
413 std::string mgmt = scanInfo.capabilities;
414 if (mgmt.find("WPA-PSK") != std::string::npos || mgmt.find("WPA2-PSK") != std::string::npos) {
415 mgmt = "WPA-PSK";
416 } else if (mgmt.find("EAP") != std::string::npos) {
417 mgmt = "WPA-EAP";
418 } else if (mgmt.find("SAE") != std::string::npos) {
419 mgmt = "SAE";
420 } else {
421 if (mgmt.find("WEP") != std::string::npos && network.wepTxKeyIndex == 0) {
422 WIFI_LOGE("The roaming network is a WEP network, but the connected network is not a WEP network.\n");
423 return false;
424 } else if (mgmt.find("WEP") == std::string::npos && network.wepTxKeyIndex != 0) {
425 WIFI_LOGE("The connected network is a WEP network, but the roaming network is not a WEP network.\n");
426 return false;
427 }
428 mgmt = "NONE";
429 }
430 if (mgmt == network.keyMgmt) {
431 WIFI_LOGD("The Current network bssid %{public}s signal strength is %{public}d",
432 MacAnonymize(info.bssid).c_str(), info.rssi);
433 WIFI_LOGD("The Roaming network bssid %{public}s signal strength is %{public}d",
434 MacAnonymize(scanInfo.bssid).c_str(), scanInfo.rssi);
435 int rssi = scanInfo.rssi - info.rssi;
436 if (rssi > MIN_ROAM_RSSI_DIFF) {
437 WIFI_LOGD("Roming network rssi - Current network rssi > 6.");
438 electedDevice.ssid = scanInfo.ssid;
439 electedDevice.bssid = scanInfo.bssid;
440 return true;
441 } else {
442 WIFI_LOGD("Roming network rssi - Current network rssi < 6.");
443 }
444 } else {
445 WIFI_LOGE("The encryption mode does not match.\n");
446 }
447 }
448 return false;
449 }
450
AllowAutoSelectDevice(OHOS::Wifi::WifiLinkedInfo & info)451 bool StaAutoConnectService::AllowAutoSelectDevice(OHOS::Wifi::WifiLinkedInfo &info)
452 {
453 if (info.connState == DISCONNECTED || info.connState == UNKNOWN) {
454 return true;
455 }
456 WIFI_LOGI("Current linkInfo state:[%{public}d %{public}s] is not in DISCONNECTED state, skip network selection.",
457 info.connState, magic_enum::Enum2Name(info.connState).c_str());
458 return false;
459 }
460
AllowAutoSelectDevice(const std::vector<InterScanInfo> & scanInfos,WifiLinkedInfo & info)461 bool StaAutoConnectService::AllowAutoSelectDevice(const std::vector<InterScanInfo> &scanInfos, WifiLinkedInfo &info)
462 {
463 WIFI_LOGI("Allow auto select device, connState=%{public}d %{public}s, detailedState=%{public}d %{public}s\n",
464 info.connState, magic_enum::Enum2Name(info.connState).c_str(), info.detailedState,
465 magic_enum::Enum2Name(info.detailedState).c_str());
466 if (scanInfos.empty()) {
467 WIFI_LOGE("No network,skip network selection.\n");
468 return false;
469 }
470
471 switch (info.detailedState) {
472 case DetailedState::WORKING:
473 /* Configure whether to automatically switch the network. */
474 if (!WifiSettings::GetInstance().GetWhetherToAllowNetworkSwitchover(m_instId)) {
475 WIFI_LOGE("Automatic network switching is not allowed in user configuration.\n");
476 return false;
477 }
478 /* Indicates whether the minimum interval is the minimum interval since the last network selection. */
479 if (selectDeviceLastTime != 0) {
480 int gap = static_cast<int>(time(nullptr)) - selectDeviceLastTime;
481 if (gap < MIN_SELECT_NETWORK_TIME) {
482 WIFI_LOGE("%ds time before we selected the network(30s).\n", gap);
483 return false;
484 }
485 }
486
487 if (!CurrentDeviceGoodEnough(scanInfos, info)) {
488 WIFI_LOGI("The current network is insuffice.\n");
489 return true;
490 }
491 return false;
492
493 case DetailedState::DISCONNECTED:
494 case DetailedState::CONNECTION_TIMEOUT:
495 case DetailedState::FAILED:
496 case DetailedState::CONNECTION_REJECT:
497 case DetailedState::CONNECTION_FULL:
498 WIFI_LOGI("Auto Select is allowed, detailedState: %{public}d\n", info.detailedState);
499 return true;
500 case DetailedState::PASSWORD_ERROR:
501 WIFI_LOGI("Password error, clear blocked bssids, auto connect to ap quickly.\n");
502 ClearAllBlockedBssids();
503 return true;
504
505 case DetailedState::NOTWORKING:
506 WIFI_LOGI("The current network cannot access the Internet.\n");
507 /* Configure whether to automatically switch the network. */
508 if (!WifiSettings::GetInstance().GetWhetherToAllowNetworkSwitchover(m_instId)) {
509 WIFI_LOGE("Automatic network switching is not allowed in user configuration.\n");
510 return false;
511 }
512 return true;
513
514 default:
515 WIFI_LOGE("not allowed auto select!\n");
516 return false;
517 }
518 return false;
519 }
520
CurrentDeviceGoodEnough(const std::vector<InterScanInfo> & scanInfos,WifiLinkedInfo & info)521 bool StaAutoConnectService::CurrentDeviceGoodEnough(const std::vector<InterScanInfo> &scanInfos, WifiLinkedInfo &info)
522 {
523 WIFI_LOGI("Enter CurrentDeviceGoodEnough.\n");
524
525 WifiDeviceConfig network;
526
527 /* The network is deleted */
528 if (WifiSettings::GetInstance().GetDeviceConfig(info.networkId, network) == -1) {
529 WIFI_LOGE("The network is deleted.\n");
530 return false;
531 }
532
533 int userLastSelectedNetworkId = WifiConfigCenter::GetInstance().GetUserLastSelectedNetworkId(m_instId);
534 if (userLastSelectedNetworkId != INVALID_NETWORK_ID && userLastSelectedNetworkId == network.networkId) {
535 time_t userLastSelectedNetworkTimeVal = WifiConfigCenter::GetInstance().GetUserLastSelectedNetworkTimeVal(
536 m_instId);
537 time_t now = time(nullptr);
538 int interval = static_cast<int>(now - userLastSelectedNetworkTimeVal);
539 if (interval <= TIME_FROM_LAST_SELECTION) {
540 WIFI_LOGI("(60s)Current user recent selections time is %ds.\n", interval);
541 return true;
542 }
543 }
544
545 /* Temporary network unqualified */
546 if (network.isEphemeral) {
547 WIFI_LOGE("The network is isEphemeral.\n");
548 return false;
549 }
550
551 if (network.keyMgmt == "NONE" || network.keyMgmt.size() == 0) {
552 WIFI_LOGE("This network No keyMgmt.\n");
553 return false;
554 }
555
556 /* The signal strength on the live network does not meet requirements. */
557 if (info.rssi < RSSI_DELIMITING_VALUE) {
558 WIFI_LOGE("Signal strength insuffice %{public}d < -65.\n", info.rssi);
559 return false;
560 }
561 /*
562 * The network is a 2.4 GHz network and is not qualified when the 5G network
563 * is available.
564 */
565 if (Whether24GDevice(info.frequency)) {
566 if (WhetherDevice5GAvailable(scanInfos)) {
567 WIFI_LOGE("5 GHz is available when the current frequency band is 2.4 GHz.\n");
568 return false;
569 }
570 }
571 return true;
572 }
573
WhetherDevice5GAvailable(const std::vector<InterScanInfo> & scanInfos)574 bool StaAutoConnectService::WhetherDevice5GAvailable(const std::vector<InterScanInfo> &scanInfos)
575 {
576 WIFI_LOGI("Enter WhetherDevice5GAvailable.\n");
577 for (auto scaninfo : scanInfos) {
578 if (Whether5GDevice(scaninfo.frequency)) {
579 return true;
580 }
581 }
582 return false;
583 }
584
Whether24GDevice(int frequency)585 bool StaAutoConnectService::Whether24GDevice(int frequency)
586 {
587 if (frequency > MIN_24_FREQUENCY && frequency < MAX_24_FREQUENCY) {
588 return true;
589 } else {
590 return false;
591 }
592 }
593
Whether5GDevice(int frequency)594 bool StaAutoConnectService::Whether5GDevice(int frequency)
595 {
596 if (frequency > MIN_5_FREQUENCY && frequency < MAX_5_FREQUENCY) {
597 return true;
598 } else {
599 return false;
600 }
601 }
602
GetAvailableScanInfos(std::vector<InterScanInfo> & availableScanInfos,const std::vector<InterScanInfo> & scanInfos,std::vector<std::string> & blockedBssids,WifiLinkedInfo & info)603 void StaAutoConnectService::GetAvailableScanInfos(std::vector<InterScanInfo> &availableScanInfos,
604 const std::vector<InterScanInfo> &scanInfos, std::vector<std::string> &blockedBssids, WifiLinkedInfo &info)
605 {
606 WIFI_LOGI("Enter GetAvailableScanInfos.\n");
607 if (scanInfos.empty()) {
608 return;
609 }
610 bool scanInfosContainCurrentBssid = false;
611
612 for (auto scanInfo : scanInfos) {
613 if (scanInfo.ssid.size() == 0) {
614 continue;
615 }
616
617 /* Check whether the scanning result contains the current BSSID. */
618 if (info.connState == ConnState::CONNECTED && scanInfo.bssid == info.bssid) {
619 scanInfosContainCurrentBssid = true;
620 }
621
622 auto itr = find(blockedBssids.begin(), blockedBssids.end(), scanInfo.bssid);
623 if (itr != blockedBssids.end()) { /* Skip Blocklist Network */
624 WIFI_LOGD("Skip blocklistedBssid network, ssid: %{public}s.\n", SsidAnonymize(scanInfo.ssid).c_str());
625 continue;
626 }
627
628 /* Skipping networks with weak signals */
629 if (scanInfo.frequency < MIN_5GHZ_BAND_FREQUENCY) {
630 if (scanInfo.rssi <= MIN_RSSI_VALUE_24G) {
631 WIFI_LOGD("Skip network %{public}s with low 2.4G signals %{public}d.\n",
632 SsidAnonymize(scanInfo.ssid).c_str(), scanInfo.rssi);
633 continue;
634 }
635 } else {
636 if (scanInfo.rssi <= MIN_RSSI_VALUE_5G) {
637 WIFI_LOGD("Skip network %{public}s with low 5G signals %{public}d.\n",
638 SsidAnonymize(scanInfo.ssid).c_str(), scanInfo.rssi);
639 continue;
640 }
641 }
642 availableScanInfos.push_back(scanInfo);
643 }
644 /*
645 * Some scan requests may not include channels for the currently connected
646 * network, so the currently connected network will not appear in the scan
647 * results. We will not act on these scans to avoid network switching that may
648 * trigger disconnections.
649 */
650 if (info.connState == ConnState::CONNECTED && !scanInfosContainCurrentBssid) {
651 WIFI_LOGI("scanInfo is be cleared.\n");
652 availableScanInfos.clear();
653 }
654 return;
655 }
656
DisableAutoJoin(const std::string & conditionName)657 void StaAutoConnectService::DisableAutoJoin(const std::string &conditionName)
658 {
659 std::lock_guard<std::mutex> lock(autoJoinMutex);
660 WIFI_LOGI("Auto Join is disabled by %{public}s.", conditionName.c_str());
661 autoJoinConditionsMap.insert_or_assign(conditionName, []() { return false; });
662 }
663
EnableAutoJoin(const std::string & conditionName)664 void StaAutoConnectService::EnableAutoJoin(const std::string &conditionName)
665 {
666 std::lock_guard<std::mutex> lock(autoJoinMutex);
667 WIFI_LOGI("Auto Join disabled by %{public}s is released.", conditionName.c_str());
668 autoJoinConditionsMap.erase(conditionName);
669 }
670
RegisterAutoJoinCondition(const std::string & conditionName,const std::function<bool ()> & autoJoinCondition)671 void StaAutoConnectService::RegisterAutoJoinCondition(const std::string &conditionName,
672 const std::function<bool()> &autoJoinCondition)
673 {
674 if (!autoJoinCondition) {
675 WIFI_LOGE("the condition of %{public}s is empty.", conditionName.c_str());
676 return;
677 }
678 std::lock_guard<std::mutex> lock(autoJoinMutex);
679 WIFI_LOGI("Auto Join condition of %{public}s is registered.", conditionName.c_str());
680 autoJoinConditionsMap.insert_or_assign(conditionName, autoJoinCondition);
681 }
682
DeregisterAutoJoinCondition(const std::string & conditionName)683 void StaAutoConnectService::DeregisterAutoJoinCondition(const std::string &conditionName)
684 {
685 std::lock_guard<std::mutex> lock(autoJoinMutex);
686 WIFI_LOGI("Auto Join condition of %{public}s is deregistered.", conditionName.c_str());
687 autoJoinConditionsMap.erase(conditionName);
688 }
689
IsAllowAutoJoin()690 bool StaAutoConnectService::IsAllowAutoJoin()
691 {
692 std::lock_guard<std::mutex> lock(autoJoinMutex);
693 for (auto condition = autoJoinConditionsMap.rbegin(); condition != autoJoinConditionsMap.rend(); ++condition) {
694 if (!condition->second.operator()()) {
695 WIFI_LOGI("Auto Join is not allowed because of %{public}s.", condition->first.c_str());
696 return false;
697 }
698 }
699 return true;
700 }
701 } // namespace Wifi
702 } // namespace OHOS
703