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_saved_device_appraisal.h"
16 #include "wifi_logger.h"
17 #include "wifi_settings.h"
18 #include "wifi_common_util.h"
19
20 DEFINE_WIFILOG_LABEL("StaSavedDeviceAppraisal");
21
22 #define BINARY_CODE 0001
23 #define LAST_SELECTION_SCORE_DECAY_S 300
24 #define MAX(A, B) (((A) >= (B)) ? (A) : (B))
25 namespace OHOS {
26 namespace Wifi {
StaSavedDeviceAppraisal(bool supportFmRoamingFlag)27 StaSavedDeviceAppraisal::StaSavedDeviceAppraisal(bool supportFmRoamingFlag)
28 : signalScorePerLevel(WifiSettings::GetInstance().GetScoretacticsScoreSlope()),
29 signalBaseScore(WifiSettings::GetInstance().GetScoretacticsInitScore()),
30 sameBssidScore(WifiSettings::GetInstance().GetScoretacticsSameBssidScore()),
31 sameDeviceScore(WifiSettings::GetInstance().GetScoretacticsSameNetworkScore()),
32 frequency5GHzScore(WifiSettings::GetInstance().GetScoretacticsFrequency5GHzScore()),
33 userSelectedDeviceScore(WifiSettings::GetInstance().GetScoretacticsLastSelectionScore()),
34 safetyDeviceScore(WifiSettings::GetInstance().GetScoretacticsSecurityScore()),
35 normalDeviceScore(WifiSettings::GetInstance().GetScoretacticsNormalScore()),
36 firmwareRoamFlag(supportFmRoamingFlag)
37 {}
~StaSavedDeviceAppraisal()38 StaSavedDeviceAppraisal::~StaSavedDeviceAppraisal()
39 {
40 WIFI_LOGI("Enter StaSavedDeviceAppraisal::~StaSavedDeviceAppraisal.\n");
41 }
42
DeviceAppraisals(WifiDeviceConfig & electedDevice,std::vector<InterScanInfo> & scanInfos,WifiLinkedInfo & info)43 ErrCode StaSavedDeviceAppraisal::DeviceAppraisals(
44 WifiDeviceConfig &electedDevice, std::vector<InterScanInfo> &scanInfos, WifiLinkedInfo &info)
45 {
46 WIFI_LOGD("Enter StaSavedDeviceAppraisal::DeviceAppraisals.\n");
47 int highestScore = 0;
48 int sign = 0;
49 InterScanInfo scanInfoElected;
50 scanInfoElected.rssi = VALUE_LIMIT_MIN_RSSI;
51
52 for (auto scanInfo : scanInfos) {
53 WifiDeviceConfig device;
54 if (WifiSettings::GetInstance().GetDeviceConfig(scanInfo.bssid, DEVICE_CONFIG_INDEX_BSSID, device) != 0 &&
55 WifiSettings::GetInstance().GetDeviceConfig(scanInfo.ssid, DEVICE_CONFIG_INDEX_SSID, device) != 0) {
56 WIFI_LOGD("Skip unsaved ssid Network %{public}s.", SsidAnonymize(scanInfo.ssid).c_str());
57 continue;
58 }
59
60 if (WhetherSkipDevice(device)) {
61 continue;
62 }
63
64 int score = 0;
65 AppraiseDeviceQuality(score, scanInfo, device, info, device.connFailedCount >= MAX_RETRY_COUNT);
66 WIFI_LOGD("The device networkId:%{public}d ssid:%{public}s score:%{public}d rssi:%{public}d.",
67 device.networkId, SsidAnonymize(scanInfo.ssid).c_str(), score, scanInfo.rssi);
68 if (CheckHigherPriority(score, highestScore, scanInfo.rssi, scanInfoElected.rssi)) {
69 highestScore = score;
70 scanInfoElected.rssi = scanInfo.rssi;
71 electedDevice = device;
72 sign = 1;
73 WIFI_LOGD("set highestScore: %{public}d, ssid: %{public}s", highestScore, SsidAnonymize(device.ssid).c_str());
74 } else {
75 WIFI_LOGD("The config %{public}s is ignored!\n", MacAnonymize(scanInfo.ssid).c_str());
76 }
77 }
78 if (sign == 1) {
79 WIFI_LOGI("DeviceAppraisals, Selected device, networkId:%{public}d, ssid:%{public}s, bssid:%{public}s.",
80 electedDevice.networkId, SsidAnonymize(electedDevice.ssid).c_str(),
81 MacAnonymize(electedDevice.bssid).c_str());
82 if (info.connState == ConnState::CONNECTED && electedDevice.networkId == info.networkId) {
83 WifiDeviceConfig networkInfo;
84 electedDevice = networkInfo;
85 WIFI_LOGI("The electedDevice is the current connected device. Skip the device selection.");
86 return WIFI_OPT_FAILED;
87 } else {
88 WIFI_LOGI("The device is selected successfully.\n");
89 return WIFI_OPT_SUCCESS;
90 }
91 } else {
92 WIFI_LOGI("Skip all scan results.\n");
93 return WIFI_OPT_FAILED;
94 }
95 }
96
WhetherSkipDevice(WifiDeviceConfig & device)97 bool StaSavedDeviceAppraisal::WhetherSkipDevice(WifiDeviceConfig &device)
98 {
99 /* Skip this type of device and evaluate it by other appraisals */
100 if (device.isPasspoint || device.isEphemeral) {
101 WIFI_LOGI("Skip isPasspoint or isEphemeral Network %{public}s.", SsidAnonymize(device.ssid).c_str());
102 return true;
103 }
104
105 if (device.status == static_cast<int>(WifiDeviceConfigStatus::DISABLED)) {
106 WIFI_LOGI("Skip disabled Network %{public}s.", SsidAnonymize(device.ssid).c_str());
107 return true;
108 }
109 std::string bssid = WifiSettings::GetInstance().GetConnectTimeoutBssid();
110 if (!bssid.empty() && bssid == device.bssid) {
111 WIFI_LOGI("Skip the connect timeout Network %{public}s.", SsidAnonymize(device.ssid).c_str());
112 return true;
113 }
114 return false;
115 }
116
AppraiseDeviceQuality(int & score,InterScanInfo & scanInfo,WifiDeviceConfig & device,WifiLinkedInfo & info,bool flip)117 void StaSavedDeviceAppraisal::AppraiseDeviceQuality(int &score, InterScanInfo &scanInfo,
118 WifiDeviceConfig &device, WifiLinkedInfo &info, bool flip)
119 {
120 WIFI_LOGD("Enter StaSavedDeviceAppraisal::AppraiseDeviceQuality.\n");
121 int rssi = scanInfo.rssi;
122 /* Converts a signal to a grid number */
123 int signalStrength = CalculateSignalBars(rssi, MAX_SIGNAL_BAR_NUM);
124 /* Signal strength score */
125 score += signalBaseScore + signalStrength * signalScorePerLevel;
126 WIFI_LOGD("signalstrength score is %{public}d.\n", score);
127
128 /* 5 GHz frequency band: bonus point */
129 if (Whether5GDevice(scanInfo.frequency)) {
130 score += frequency5GHzScore;
131 WIFI_LOGD("5G score is %{public}d.\n", frequency5GHzScore);
132 }
133
134 /* normal device config: bonus point */
135 if (device.uid == WIFI_INVALID_UID) {
136 score += normalDeviceScore;
137 WIFI_LOGD("normal score is %{public}d.\n", normalDeviceScore);
138 }
139
140 /* Bonus points for last user selection */
141 int userLastSelectedNetworkId = WifiSettings::GetInstance().GetUserLastSelectedNetworkId();
142 if (userLastSelectedNetworkId != INVALID_NETWORK_ID && userLastSelectedNetworkId == device.networkId) {
143 time_t userLastSelectedNetworkTimeVal = WifiSettings::GetInstance().GetUserLastSelectedNetworkTimeVal();
144 time_t now = time(0);
145 time_t timeDifference = now - userLastSelectedNetworkTimeVal;
146 /*
147 * Basic score of the device selected by the user: 120.
148 * One point is deducted from every 5 points since the time when the user
149 * selects the device.
150 */
151 if (timeDifference > 0) {
152 int decay = static_cast<int>(timeDifference / LAST_SELECTION_SCORE_DECAY_S);
153 int bonus = MAX((userSelectedDeviceScore - decay), (0));
154 score += bonus;
155 WIFI_LOGI("lastselected score is %{public}d.\n", bonus);
156 }
157 }
158 /*
159 * If the current device is the same as the elected device, bonus points
160 * are added.
161 */
162 if (info.detailedState == DetailedState::WORKING && scanInfo.ssid == info.ssid) {
163 score += sameDeviceScore;
164 WIFI_LOGI("samenetwork score is %{public}d.\n", sameDeviceScore);
165 /*
166 * When firmware roaming is supported, the same BSSID is added to different
167 * BSSIDs.
168 */
169 if (firmwareRoamFlag && scanInfo.bssid != info.bssid) {
170 score += sameBssidScore;
171 WIFI_LOGI("roamingsupport score is %{public}d.\n", sameBssidScore);
172 }
173 }
174
175 if (info.detailedState == DetailedState::WORKING && info.bssid == scanInfo.bssid) {
176 score += sameBssidScore;
177 WIFI_LOGI("SameBssid score is %{public}d.\n", sameBssidScore);
178 }
179
180 if (device.keyMgmt != "NONE" && device.keyMgmt.size() != 0) {
181 score += safetyDeviceScore;
182 WIFI_LOGI("security score is %{public}d.\n", safetyDeviceScore);
183 }
184
185 if (flip) { // lowest priority ssid, filp the score
186 score = 0 - score;
187 }
188 }
189
Whether5GDevice(int frequency)190 bool StaSavedDeviceAppraisal::Whether5GDevice(int frequency)
191 {
192 if (frequency > MIN_5_FREQUENCY && frequency < MAX_5_FREQUENCY) {
193 return true;
194 } else {
195 return false;
196 }
197 }
198
CalculateSignalBars(int rssi,int signalBars)199 int StaSavedDeviceAppraisal::CalculateSignalBars(int rssi, int signalBars)
200 {
201 WIFI_LOGD("Enter StaSavedDeviceAppraisal CalculateSignalBars");
202 if (rssi <= VALUE_LIMIT_MIN_RSSI) {
203 return 0;
204 } else if (rssi >= VALUE_LIMIT_MAX_RSSI) {
205 return signalBars - 1;
206 } else {
207 float inputRange = (VALUE_LIMIT_MAX_RSSI - VALUE_LIMIT_MIN_RSSI);
208 float outputRange = (signalBars - 1);
209 return static_cast<int>(static_cast<float>(rssi - VALUE_LIMIT_MIN_RSSI) * outputRange / inputRange);
210 }
211 }
212
CheckHigherPriority(int score,int lastScore,int rssi,int selectedRssi)213 bool StaSavedDeviceAppraisal::CheckHigherPriority(int score, int lastScore, int rssi, int selectedRssi)
214 {
215 bool higerPriority = false;
216 if (lastScore == 0) {
217 higerPriority = true; // first higerPriority
218 } else if (lastScore > 0) {
219 higerPriority = score > lastScore || // compare score, if equal then compare rssi
220 (score == lastScore && rssi > selectedRssi);
221 } else {
222 if (score >= 0) {
223 higerPriority = true; // > 0 higher priority
224 } else {
225 higerPriority = score < lastScore || // both low priority then compare score
226 (score == lastScore && rssi > selectedRssi);
227 }
228 }
229 return higerPriority;
230 }
231 } // namespace Wifi
232 } // namespace OHOS