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 BOTTOM_TIME_BASE_SCORE = -1000000;
32 constexpr int MAX_RECENT_SELECTION_SECONDS = 8 * 60 * 60;
33 constexpr int MIN_5G_FREQUENCY = 5160;
34 constexpr int MAX_5G_FREQUENCY = 5865;
35 constexpr int WIFI_5G_BAND_SCORE = 50;
36 constexpr int WIFI_2G_BAND_SCORE = 20;
37 constexpr int SECURITY_BONUS_SCORE = 5;
38 constexpr int RSSI_LEVEL_FOUR_SCORE = 80;
39 constexpr int RSSI_LEVEL_THREE_SCORE = 60;
40 constexpr int RSSI_LEVEL_TWO_SCORE = 20;
41 constexpr int WIFI_DEFAULT_SCORE = -1;
42 constexpr int RSSI_LEVEL_TWO_SCORE_5G = 40;
43 constexpr int RSSI_LEVEL_TWO_SCORE_2G = 20;
44 constexpr int SIGNAL_LEVEL_TWO = 2;
45 constexpr int SIGNAL_LEVEL_THREE = 3;
46 constexpr int SIGNAL_LEVEL_FOUR = 4;
47 constexpr int MIN_RSSI = -128;
48 constexpr int INTERNET_ACCESS_AWARD = 2;
49 constexpr int EMPTY_NETWORK_STATUS_HISTORY_AWARD = 1;
50 constexpr int MAX_HISTORY_NETWORK_STATUS_NUM = 10;
51 constexpr int HISTORY_NETWORK_STATUS_WEIGHTED_SCORE[MAX_HISTORY_NETWORK_STATUS_NUM] = {
52 81920, 40960, 20480, 10240, 5120, 2560, 1280, 640, 320, 160};
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 scoreResult.scorerName = "ThroughputScorer";
132 double rssiBaseScore = GetRssiBaseScore(networkCandidate);
133 double savedNetworkAward = GetSavedNetworkAward(networkCandidate);
134 scoreResult.score = rssiBaseScore + savedNetworkAward;
135 if (IsSecurityNetwork(networkCandidate)) {
136 scoreResult.score += SECURITY_AWARD_SCORE;
137 }
138
139 // It is suggestion network that the network priority be very low.
140 if (networkCandidate.wifiDeviceConfig.uid != -1 &&
141 networkCandidate.wifiDeviceConfig.isShared == 0) {
142 scoreResult.score += BOTTOM_TIME_BASE_SCORE;
143 return;
144 }
145
146 if (IsRecentUserSelected(networkCandidate)) {
147 scoreResult.score = TOP_TIME_BASE_SCORE + rssiBaseScore + savedNetworkAward;
148 return;
149 }
150 }
151
SecurityBonusScorer()152 SecurityBonusScorer::SecurityBonusScorer() : SimpleWifiScorer("securityScore") {}
153
IsHigherSecurityTypeFromScanResult(const InterScanInfo & interScanInfo)154 bool SecurityBonusScorer::IsHigherSecurityTypeFromScanResult(const InterScanInfo &interScanInfo)
155 {
156 return IsEncryptionSae(interScanInfo) || IsEncryptionPskSaeTransition(interScanInfo)
157 || IsEncryptionOwe(interScanInfo) || IsEncryptionOweTransition(interScanInfo)
158 || IsWpa3EnterpriseOnlyNetwork(interScanInfo) || IsWpa3EnterpriseTransitionNetwork(interScanInfo);
159 }
160
IsEncryptionSae(const InterScanInfo & interScanInfo)161 bool SecurityBonusScorer::IsEncryptionSae(const InterScanInfo &interScanInfo)
162 {
163 return ExistSecurityType(interScanInfo, "SAE");
164 }
165
IsEncryptionPskSaeTransition(const InterScanInfo & interScanInfo)166 bool SecurityBonusScorer::IsEncryptionPskSaeTransition(const InterScanInfo &interScanInfo)
167 {
168 return ExistSecurityType(interScanInfo, "PSK") && ExistSecurityType(interScanInfo, "SAE");
169 }
170
IsEncryptionOwe(const InterScanInfo & interScanInfo)171 bool SecurityBonusScorer::IsEncryptionOwe(const InterScanInfo &interScanInfo)
172 {
173 return ExistSecurityType(interScanInfo, "OWE");
174 }
175
IsEncryptionOweTransition(const InterScanInfo & interScanInfo)176 bool SecurityBonusScorer::IsEncryptionOweTransition(const InterScanInfo &interScanInfo)
177 {
178 return ExistSecurityType(interScanInfo, "OWE_TRANSITION");
179 }
180
IsWpa3EnterpriseOnlyNetwork(const InterScanInfo & interScanInfo)181 bool SecurityBonusScorer::IsWpa3EnterpriseOnlyNetwork(const InterScanInfo &interScanInfo)
182 {
183 return ExistSecurityType(interScanInfo, "EAP/SHA256") && !ExistSecurityType(interScanInfo, "EAP/SHA1")
184 && ExistSecurityType(interScanInfo, "RSN") && !ExistSecurityType(interScanInfo, "WEP")
185 && !ExistSecurityType(interScanInfo, "TKIP")
186 && (ExistSecurityType(interScanInfo, "[MFPR]") || ExistSecurityType(interScanInfo, "[PMFR]"))
187 && (ExistSecurityType(interScanInfo, "[MFPC]") || ExistSecurityType(interScanInfo, "[PMFC]"));
188 }
189
IsWpa3EnterpriseTransitionNetwork(const InterScanInfo & interScanInfo)190 bool SecurityBonusScorer::IsWpa3EnterpriseTransitionNetwork(const InterScanInfo &interScanInfo)
191 {
192 return ExistSecurityType(interScanInfo, "EAP/SHA1") && ExistSecurityType(interScanInfo, "EAP/SHA256")
193 && ExistSecurityType(interScanInfo, "RSN") && !ExistSecurityType(interScanInfo, "WEP")
194 && !ExistSecurityType(interScanInfo, "TKIP")
195 && !(ExistSecurityType(interScanInfo, "[MFPR]") || ExistSecurityType(interScanInfo, "[PMFR]"))
196 && (ExistSecurityType(interScanInfo, "[MFPC]") || ExistSecurityType(interScanInfo, "[PMFC]"));
197 }
198
ExistSecurityType(const InterScanInfo & interScanInfo,const std::string & securityType)199 bool SecurityBonusScorer::ExistSecurityType(const InterScanInfo &interScanInfo, const std::string &securityType)
200 {
201 return interScanInfo.capabilities.find(securityType) != std::string::npos;
202 }
203
Score(NetworkCandidate & networkCandidate)204 double SecurityBonusScorer::Score(NetworkCandidate &networkCandidate)
205 {
206 return IsHigherSecurityTypeFromScanResult(networkCandidate.interScanInfo) ? SECURITY_BONUS_SCORE : 0;
207 }
208
RssiLevelBonusScorer()209 RssiLevelBonusScorer::RssiLevelBonusScorer() : SimpleWifiScorer("rssiLevelScore") {}
210
Score(NetworkCandidate & networkCandidate)211 double RssiLevelBonusScorer::Score(NetworkCandidate &networkCandidate)
212 {
213 auto &scanInfo = networkCandidate.interScanInfo;
214 int frequency = networkCandidate.interScanInfo.frequency;
215 int currentSignalLevel = WifiSettings::GetInstance().GetSignalLevel(scanInfo.rssi, scanInfo.band);
216 if (currentSignalLevel == SIGNAL_LEVEL_FOUR) {
217 return RSSI_LEVEL_FOUR_SCORE;
218 }
219 if (currentSignalLevel == SIGNAL_LEVEL_THREE) {
220 return RSSI_LEVEL_THREE_SCORE;
221 }
222 if (currentSignalLevel == SIGNAL_LEVEL_TWO) {
223 if (frequency >= MIN_5G_FREQUENCY && frequency <= MAX_5G_FREQUENCY) {
224 return RSSI_LEVEL_TWO_SCORE_5G;
225 } else {
226 return RSSI_LEVEL_TWO_SCORE_2G;
227 }
228 }
229 return 0;
230 }
231
SignalLevelScorer()232 SignalLevelScorer::SignalLevelScorer() : SimpleWifiScorer("SignalLevelScorer") {}
233
Score(NetworkCandidate & networkCandidate)234 double SignalLevelScorer::Score(NetworkCandidate &networkCandidate)
235 {
236 auto &scanInfo = networkCandidate.interScanInfo;
237 int signalLevel = WifiSettings::GetInstance().GetSignalLevel(scanInfo.rssi, scanInfo.band);
238 int32_t levelScore = 0;
239 switch (signalLevel) {
240 case SIGNAL_LEVEL_FOUR:
241 levelScore = RSSI_LEVEL_FOUR_SCORE;
242 break;
243 case SIGNAL_LEVEL_THREE:
244 levelScore = RSSI_LEVEL_THREE_SCORE;
245 break;
246 case SIGNAL_LEVEL_TWO:
247 levelScore = RSSI_LEVEL_TWO_SCORE;
248 break;
249 default:
250 levelScore = WIFI_DEFAULT_SCORE;
251 break;
252 }
253
254 return levelScore;
255 }
256
Network5gBonusScorer()257 Network5gBonusScorer::Network5gBonusScorer() : SimpleWifiScorer("5gBonusScore") {}
258
Score(NetworkCandidate & networkCandidate)259 double Network5gBonusScorer::Score(NetworkCandidate &networkCandidate)
260 {
261 int frequency = networkCandidate.interScanInfo.frequency;
262 return frequency >= MIN_5G_FREQUENCY && frequency <= MAX_5G_FREQUENCY ? WIFI_5G_BAND_SCORE : WIFI_2G_BAND_SCORE;
263 }
264
SavedNetworkScorer(const std::string & scorerName)265 SavedNetworkScorer::SavedNetworkScorer(const std::string &scorerName) : CompositeWifiScorer(scorerName)
266 {
267 AddScorer(std::make_shared<RssiLevelBonusScorer>());
268 AddScorer(std::make_shared<SecurityBonusScorer>());
269 AddScorer(std::make_shared<Network5gBonusScorer>());
270 ExternalWifiCommonBuildManager::GetInstance().BuildScore(
271 TagType::HAS_INTERNET_NETWORK_SELECTOR_SCORE_WIFI_CATEGORY_TAG, *this);
272 }
273
NoInternetNetworkStatusHistoryScorer()274 NoInternetNetworkStatusHistoryScorer::NoInternetNetworkStatusHistoryScorer()
275 : SimpleWifiScorer("NoInternetNetworkStatusHistoryScorer") {}
276
Score(NetworkCandidate & networkCandidate)277 double NoInternetNetworkStatusHistoryScorer::Score(NetworkCandidate &networkCandidate)
278 {
279 double score = 0;
280 std::vector<int> vNetworkStatusHistory{};
281 vNetworkStatusHistory = NetworkStatusHistoryManager::GetCurrentNetworkStatusHistory2Array(
282 networkCandidate.wifiDeviceConfig.networkStatusHistory);
283
284 int nSize = (int)vNetworkStatusHistory.size();
285 for (int i = 0; i < nSize; i++) {
286 if (i >= MAX_HISTORY_NETWORK_STATUS_NUM) {
287 break;
288 }
289 score += HISTORY_NETWORK_STATUS_WEIGHTED_SCORE[i] * vNetworkStatusHistory[i];
290 }
291 return score;
292 }
293
ApQualityScorer(const std::string & scorerName)294 ApQualityScorer::ApQualityScorer(const std::string &scorerName) : CompositeWifiScorer(scorerName)
295 {
296 AddScorer(std::make_shared<SignalLevelScorer>());
297 AddScorer(std::make_shared<Network5gBonusScorer>());
298 ExternalWifiCommonBuildManager::GetInstance().BuildScore(
299 TagType::HAS_INTERNET_NETWORK_SELECTOR_SCORE_WIFI_CATEGORY_TAG, *this);
300 AddScorer(std::make_shared<SecurityBonusScorer>());
301 }
302 }
303