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