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 <iostream>
17 #include "wifi_scorer_impl.h"
18 #include "wifi_config_center.h"
19 #include "network_status_history_manager.h"
20 #include "external_wifi_common_builder_manager.h"
21 #include "wifi_logger.h"
22
23 namespace OHOS::Wifi::NetworkSelection {
24 DEFINE_WIFILOG_LABEL("WifiScorerImpl")
25 namespace {
26 constexpr int SUFFICIENT_RSSI_5G = -70;
27 constexpr int SUFFICIENT_RSSI_2G = -73;
28 constexpr int RSSI_SCORE_OFFSET = 85;
29 constexpr int RSSI_SCORE_SLOPE_IS_4 = 4;
30 constexpr int TOP_TIME_BASE_SCORE = 1000000;
31 constexpr int MAX_RECENT_SELECTION_SECONDS = 8 * 60 * 60;
32 constexpr int MIN_5G_FREQUENCY = 5160;
33 constexpr int MAX_5G_FREQUENCY = 5865;
34 constexpr int WIFI_5G_BAND_SCORE = 50;
35 constexpr int WIFI_2G_BAND_SCORE = 20;
36 constexpr int SECURITY_BONUS_SCORE = 5;
37 constexpr int RSSI_LEVEL_FOUR_SCORE = 80;
38 constexpr int RSSI_LEVEL_THREE_SCORE = 60;
39 constexpr int RSSI_LEVEL_TWO_SCORE = 20;
40 constexpr int WIFI_DEFAULT_SCORE = -1;
41 constexpr int RSSI_LEVEL_TWO_SCORE_5G = 40;
42 constexpr int RSSI_LEVEL_TWO_SCORE_2G = 20;
43 constexpr int SIGNAL_LEVEL_TWO = 2;
44 constexpr int SIGNAL_LEVEL_THREE = 3;
45 constexpr int SIGNAL_LEVEL_FOUR = 4;
46 constexpr int MIN_RSSI = -128;
47 constexpr int INTERNET_ACCESS_AWARD = 2;
48 constexpr int EMPTY_NETWORK_STATUS_HISTORY_AWARD = 1;
49 constexpr int MAX_HISTORY_NETWORK_STATUS_NUM = 10;
50 constexpr int HISTORY_NETWORK_STATUS_WEIGHTED_SCORE[MAX_HISTORY_NETWORK_STATUS_NUM] = {
51 81920, 40960, 20480, 10240, 5120, 2560, 1280, 640, 320, 160};
52 }
53
RssiScorer()54 RssiScorer::RssiScorer() : SimpleWifiScorer("rssiScorer") {}
55
Score(NetworkCandidate & networkCandidate)56 double RssiScorer::Score(NetworkCandidate &networkCandidate)
57 {
58 if (networkCandidate.interScanInfo.rssi < MIN_RSSI) {
59 return MIN_RSSI;
60 } else if (networkCandidate.interScanInfo.rssi > 0) {
61 return 0;
62 }
63 return networkCandidate.interScanInfo.rssi;
64 }
65
LastHaveInternetTimeScorer()66 LastHaveInternetTimeScorer::LastHaveInternetTimeScorer() : SimpleWifiScorer("lastHaveInternetTimeScorer") {}
67
Score(NetworkCandidate & networkCandidate)68 double LastHaveInternetTimeScorer::Score(NetworkCandidate &networkCandidate)
69 {
70 if (networkCandidate.wifiDeviceConfig.lastHasInternetTime > 0) {
71 return static_cast<double>(networkCandidate.wifiDeviceConfig.lastHasInternetTime);
72 }
73 return 0;
74 }
75
NetworkStatusHistoryScorer()76 NetworkStatusHistoryScorer::NetworkStatusHistoryScorer() : SimpleWifiScorer("networkStatusHistoryScorer") {}
77
Score(NetworkCandidate & networkCandidate)78 double NetworkStatusHistoryScorer::Score(NetworkCandidate &networkCandidate)
79 {
80 auto networkStatusHistory = networkCandidate.wifiDeviceConfig.networkStatusHistory;
81 if (NetworkStatusHistoryManager::IsInternetAccessByHistory(networkStatusHistory)) {
82 return INTERNET_ACCESS_AWARD;
83 } else if (NetworkStatusHistoryManager::IsEmptyNetworkStatusHistory(networkStatusHistory)) {
84 return EMPTY_NETWORK_STATUS_HISTORY_AWARD;
85 }
86 return 0;
87 }
88
GetRssiBaseScore(NetworkCandidate & networkCandidate)89 double ThroughputScorer::GetRssiBaseScore(NetworkCandidate &networkCandidate)
90 {
91 int rssi = networkCandidate.interScanInfo.rssi;
92 if (networkCandidate.interScanInfo.band == static_cast<int>(BandType::BAND_2GHZ)) {
93 rssi = rssi > SUFFICIENT_RSSI_2G ? SUFFICIENT_RSSI_2G : rssi;
94 } else {
95 rssi = rssi > SUFFICIENT_RSSI_5G ? SUFFICIENT_RSSI_5G : rssi;
96 }
97 return (rssi + RSSI_SCORE_OFFSET) * RSSI_SCORE_SLOPE_IS_4;
98 }
99
GetSavedNetworkAward(NetworkCandidate & networkCandidate)100 double ThroughputScorer::GetSavedNetworkAward(NetworkCandidate &networkCandidate)
101 {
102 return networkCandidate.wifiDeviceConfig.isEphemeral ? 0 : SAVED_NETWORK_AWARD_SCORE;
103 }
104
IsRecentUserSelected(NetworkCandidate & networkCandidate) const105 bool ThroughputScorer::IsRecentUserSelected(NetworkCandidate &networkCandidate) const
106 {
107 auto userLastSelectedNetworkId = WifiConfigCenter::GetInstance().GetUserLastSelectedNetworkId();
108 if (userLastSelectedNetworkId != INVALID_NETWORK_ID
109 && userLastSelectedNetworkId == networkCandidate.wifiDeviceConfig.networkId) {
110 time_t userLastSelectedNetworkTimeVal = WifiConfigCenter::GetInstance().GetUserLastSelectedNetworkTimeVal();
111 auto now = time(nullptr);
112 if (now < 0) {
113 WIFI_LOGW("time return invalid!\n.");
114 return false;
115 }
116 return (now - userLastSelectedNetworkTimeVal) < MAX_RECENT_SELECTION_SECONDS;
117 }
118 return false;
119 }
120
IsSecurityNetwork(NetworkCandidate & networkCandidate) const121 bool ThroughputScorer::IsSecurityNetwork(NetworkCandidate &networkCandidate) const
122 {
123 return networkCandidate.wifiDeviceConfig.keyMgmt == KEY_MGMT_WEP
124 || networkCandidate.wifiDeviceConfig.keyMgmt == KEY_MGMT_WPA_PSK
125 || networkCandidate.wifiDeviceConfig.keyMgmt == KEY_MGMT_SAE
126 || networkCandidate.wifiDeviceConfig.keyMgmt == KEY_MGMT_EAP;
127 }
128
DoScore(NetworkCandidate & networkCandidate,ScoreResult & scoreResult)129 void ThroughputScorer::DoScore(NetworkCandidate &networkCandidate, ScoreResult &scoreResult)
130 {
131 double rssiBaseScore = GetRssiBaseScore(networkCandidate);
132 double savedNetworkAward = GetSavedNetworkAward(networkCandidate);
133 scoreResult.scorerName = "ThroughputScorer";
134 if (IsRecentUserSelected(networkCandidate)) {
135 scoreResult.score = TOP_TIME_BASE_SCORE + rssiBaseScore + savedNetworkAward;
136 return;
137 }
138 scoreResult.score = rssiBaseScore + savedNetworkAward;
139 if (IsSecurityNetwork(networkCandidate)) {
140 scoreResult.score += SECURITY_AWARD_SCORE;
141 }
142 }
143
SecurityBonusScorer()144 SecurityBonusScorer::SecurityBonusScorer() : SimpleWifiScorer("securityScore") {}
145
IsHigherSecurityTypeFromScanResult(const InterScanInfo & interScanInfo)146 bool SecurityBonusScorer::IsHigherSecurityTypeFromScanResult(const InterScanInfo &interScanInfo)
147 {
148 return IsEncryptionSae(interScanInfo) || IsEncryptionPskSaeTransition(interScanInfo)
149 || IsEncryptionOwe(interScanInfo) || IsEncryptionOweTransition(interScanInfo)
150 || IsWpa3EnterpriseOnlyNetwork(interScanInfo) || IsWpa3EnterpriseTransitionNetwork(interScanInfo);
151 }
152
IsEncryptionSae(const InterScanInfo & interScanInfo)153 bool SecurityBonusScorer::IsEncryptionSae(const InterScanInfo &interScanInfo)
154 {
155 return ExistSecurityType(interScanInfo, "SAE");
156 }
157
IsEncryptionPskSaeTransition(const InterScanInfo & interScanInfo)158 bool SecurityBonusScorer::IsEncryptionPskSaeTransition(const InterScanInfo &interScanInfo)
159 {
160 return ExistSecurityType(interScanInfo, "PSK") && ExistSecurityType(interScanInfo, "SAE");
161 }
162
IsEncryptionOwe(const InterScanInfo & interScanInfo)163 bool SecurityBonusScorer::IsEncryptionOwe(const InterScanInfo &interScanInfo)
164 {
165 return ExistSecurityType(interScanInfo, "OWE");
166 }
167
IsEncryptionOweTransition(const InterScanInfo & interScanInfo)168 bool SecurityBonusScorer::IsEncryptionOweTransition(const InterScanInfo &interScanInfo)
169 {
170 return ExistSecurityType(interScanInfo, "OWE_TRANSITION");
171 }
172
IsWpa3EnterpriseOnlyNetwork(const InterScanInfo & interScanInfo)173 bool SecurityBonusScorer::IsWpa3EnterpriseOnlyNetwork(const InterScanInfo &interScanInfo)
174 {
175 return ExistSecurityType(interScanInfo, "EAP/SHA256") && !ExistSecurityType(interScanInfo, "EAP/SHA1")
176 && ExistSecurityType(interScanInfo, "RSN") && !ExistSecurityType(interScanInfo, "WEP")
177 && !ExistSecurityType(interScanInfo, "TKIP")
178 && (ExistSecurityType(interScanInfo, "[MFPR]") || ExistSecurityType(interScanInfo, "[PMFR]"))
179 && (ExistSecurityType(interScanInfo, "[MFPC]") || ExistSecurityType(interScanInfo, "[PMFC]"));
180 }
181
IsWpa3EnterpriseTransitionNetwork(const InterScanInfo & interScanInfo)182 bool SecurityBonusScorer::IsWpa3EnterpriseTransitionNetwork(const InterScanInfo &interScanInfo)
183 {
184 return ExistSecurityType(interScanInfo, "EAP/SHA1") && ExistSecurityType(interScanInfo, "EAP/SHA256")
185 && ExistSecurityType(interScanInfo, "RSN") && !ExistSecurityType(interScanInfo, "WEP")
186 && !ExistSecurityType(interScanInfo, "TKIP")
187 && !(ExistSecurityType(interScanInfo, "[MFPR]") || ExistSecurityType(interScanInfo, "[PMFR]"))
188 && (ExistSecurityType(interScanInfo, "[MFPC]") || ExistSecurityType(interScanInfo, "[PMFC]"));
189 }
190
ExistSecurityType(const InterScanInfo & interScanInfo,const std::string & securityType)191 bool SecurityBonusScorer::ExistSecurityType(const InterScanInfo &interScanInfo, const std::string &securityType)
192 {
193 return interScanInfo.capabilities.find(securityType) != std::string::npos;
194 }
195
Score(NetworkCandidate & networkCandidate)196 double SecurityBonusScorer::Score(NetworkCandidate &networkCandidate)
197 {
198 return IsHigherSecurityTypeFromScanResult(networkCandidate.interScanInfo) ? SECURITY_BONUS_SCORE : 0;
199 }
200
RssiLevelBonusScorer()201 RssiLevelBonusScorer::RssiLevelBonusScorer() : SimpleWifiScorer("rssiLevelScore") {}
202
Score(NetworkCandidate & networkCandidate)203 double RssiLevelBonusScorer::Score(NetworkCandidate &networkCandidate)
204 {
205 auto &scanInfo = networkCandidate.interScanInfo;
206 int frequency = networkCandidate.interScanInfo.frequency;
207 int currentSignalLevel = WifiSettings::GetInstance().GetSignalLevel(scanInfo.rssi, scanInfo.band);
208 if (currentSignalLevel == SIGNAL_LEVEL_FOUR) {
209 return RSSI_LEVEL_FOUR_SCORE;
210 }
211 if (currentSignalLevel == SIGNAL_LEVEL_THREE) {
212 return RSSI_LEVEL_THREE_SCORE;
213 }
214 if (currentSignalLevel == SIGNAL_LEVEL_TWO) {
215 if (frequency >= MIN_5G_FREQUENCY && frequency <= MAX_5G_FREQUENCY) {
216 return RSSI_LEVEL_TWO_SCORE_5G;
217 } else {
218 return RSSI_LEVEL_TWO_SCORE_2G;
219 }
220 }
221 return 0;
222 }
223
SignalLevelScorer()224 SignalLevelScorer::SignalLevelScorer() : SimpleWifiScorer("SignalLevelScorer") {}
225
Score(NetworkCandidate & networkCandidate)226 double SignalLevelScorer::Score(NetworkCandidate &networkCandidate)
227 {
228 auto &scanInfo = networkCandidate.interScanInfo;
229 int signalLevel = WifiSettings::GetInstance().GetSignalLevel(scanInfo.rssi, scanInfo.band);
230 int32_t levelScore = 0;
231 switch (signalLevel) {
232 case SIGNAL_LEVEL_FOUR:
233 levelScore = RSSI_LEVEL_FOUR_SCORE;
234 break;
235 case SIGNAL_LEVEL_THREE:
236 levelScore = RSSI_LEVEL_THREE_SCORE;
237 break;
238 case SIGNAL_LEVEL_TWO:
239 levelScore = RSSI_LEVEL_TWO_SCORE;
240 break;
241 default:
242 levelScore = WIFI_DEFAULT_SCORE;
243 break;
244 }
245
246 return levelScore;
247 }
248
Network5gBonusScorer()249 Network5gBonusScorer::Network5gBonusScorer() : SimpleWifiScorer("5gBonusScore") {}
250
Score(NetworkCandidate & networkCandidate)251 double Network5gBonusScorer::Score(NetworkCandidate &networkCandidate)
252 {
253 int frequency = networkCandidate.interScanInfo.frequency;
254 return frequency >= MIN_5G_FREQUENCY && frequency <= MAX_5G_FREQUENCY ? WIFI_5G_BAND_SCORE : WIFI_2G_BAND_SCORE;
255 }
256
SavedNetworkScorer(const std::string & scorerName)257 SavedNetworkScorer::SavedNetworkScorer(const std::string &scorerName) : CompositeWifiScorer(scorerName)
258 {
259 AddScorer(std::make_shared<RssiLevelBonusScorer>());
260 AddScorer(std::make_shared<SecurityBonusScorer>());
261 AddScorer(std::make_shared<Network5gBonusScorer>());
262 ExternalWifiCommonBuildManager::GetInstance().BuildScore(
263 TagType::HAS_INTERNET_NETWORK_SELECTOR_SCORE_WIFI_CATEGORY_TAG, *this);
264 }
265
NoInternetNetworkStatusHistoryScorer()266 NoInternetNetworkStatusHistoryScorer::NoInternetNetworkStatusHistoryScorer()
267 : SimpleWifiScorer("NoInternetNetworkStatusHistoryScorer") {}
268
Score(NetworkCandidate & networkCandidate)269 double NoInternetNetworkStatusHistoryScorer::Score(NetworkCandidate &networkCandidate)
270 {
271 double score = 0;
272 std::vector<int> vNetworkStatusHistory{};
273 vNetworkStatusHistory = NetworkStatusHistoryManager::GetCurrentNetworkStatusHistory2Array(
274 networkCandidate.wifiDeviceConfig.networkStatusHistory);
275
276 int nSize = (int)vNetworkStatusHistory.size();
277 for (int i = 0; i < nSize; i++) {
278 if (i >= MAX_HISTORY_NETWORK_STATUS_NUM) {
279 break;
280 }
281 score += HISTORY_NETWORK_STATUS_WEIGHTED_SCORE[i] * vNetworkStatusHistory[i];
282 }
283 return score;
284 }
285
ApQualityScorer(const std::string & scorerName)286 ApQualityScorer::ApQualityScorer(const std::string &scorerName) : CompositeWifiScorer(scorerName)
287 {
288 AddScorer(std::make_shared<SignalLevelScorer>());
289 AddScorer(std::make_shared<Network5gBonusScorer>());
290 ExternalWifiCommonBuildManager::GetInstance().BuildScore(
291 TagType::HAS_INTERNET_NETWORK_SELECTOR_SCORE_WIFI_CATEGORY_TAG, *this);
292 AddScorer(std::make_shared<SecurityBonusScorer>());
293 }
294 }
295