• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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