1 /*
2 * Copyright (C) 2025 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 "select_network_data_report.h"
17 #include "sta_state_machine.h"
18 #include "wifi_common_util.h"
19 #include "wifi_logger.h"
20 #include "wifi_config_center.h"
21 #include "wifi_settings.h"
22 #include <climits>
23
24 namespace OHOS {
25 namespace Wifi {
26
27 DEFINE_WIFILOG_LABEL("SelectNetworkDataReport");
28
29 namespace WifiDataConstants {
30
31 constexpr int BEACON_RSSI_LEN = 10;
32 constexpr int CDF_LAST_LEN = 8; // txtime, uldelay 最后长度
33 constexpr int CDF_RAW_LEN = 64; // txtime, uldelay 芯片组件上报到signalpoll的最初长度
34 constexpr int CDF_PROCESS_LEN = 32; // txtime, uldelay int8 转 int16 后的长度
35 constexpr int AI_OFFSET_8 = 8;
36 constexpr int AI_OFFSET_16 = 16;
37 constexpr int AI_OFFSET_24 = 24;
38 constexpr int AI_INDEX_1 = 1;
39 constexpr int AI_INDEX_2 = 2;
40 constexpr int AI_INDEX_3 = 3;
41 constexpr int AI_CW_LEN = 2; // cwmin, cwmax
42 constexpr int CHANNEL_WIDTH_2_4G = 5; // 2.4G频段信道带宽
43 constexpr int CHANNEL_WIDTH_5G = 20; // 5G频段信道带宽
44 constexpr int QOE_INFO_LEN = 149; // signalpoll上报最长长度
45 constexpr int DELAY_TIME = 4 * 60 * 60; // 设置推送时间间隔为DELAY_TIME
46 constexpr int CONN_FAILED_COUNT_THRESHOLD = 3; // 失败上报阈值,防止关联失败重连导致上报
47 constexpr int MAX_PUSH_COUNT = 10; // 10条数据融合为一条上报
48
49 } // namespace WifiDataConstants
50
WifiDataReportService(StaStateMachine * staStateMachinePtr,int instId)51 WifiDataReportService::WifiDataReportService(StaStateMachine* staStateMachinePtr, int instId)
52 : StaSMExt(staStateMachinePtr, instId) {}
53
~WifiDataReportService()54 WifiDataReportService::~WifiDataReportService() {}
55
56
InitReportApAllInfo()57 void WifiDataReportService::InitReportApAllInfo()
58 {
59 std::lock_guard<std::mutex> lock(historyMutex_);
60 disConnFlag_ = false;
61 connEventTimepInfo_ = ConnectEventTimeInfo();
62 lastPushTime_.clear();
63 historyData_.clear();
64 }
65
GetUint32FromExt(const std::vector<uint8_t> & ext,size_t index)66 uint32_t WifiDataReportService::GetUint32FromExt(const std::vector<uint8_t>& ext, size_t index)
67 {
68 if (index + sizeof(uint32_t) - 1 >= ext.size()) {
69 WIFI_LOGE("GetUint32FromExt fail");
70 return 0;
71 }
72 return (static_cast<uint32_t>(ext[index]) |
73 static_cast<uint32_t>(ext[index + WifiDataConstants::AI_INDEX_1]) << WifiDataConstants::AI_OFFSET_8 |
74 static_cast<uint32_t>(ext[index + WifiDataConstants::AI_INDEX_2]) << WifiDataConstants::AI_OFFSET_16 |
75 static_cast<uint32_t>(ext[index + WifiDataConstants::AI_INDEX_3]) << WifiDataConstants::AI_OFFSET_24);
76 }
77
ConvertUint8ToUint16(const std::vector<uint8_t> & uint8Vec)78 std::vector<uint16_t> WifiDataReportService::ConvertUint8ToUint16(const std::vector<uint8_t>& uint8Vec)
79 {
80 std::vector<uint16_t> uint16Vec;
81 /* 确保输入向量的长度是偶数 */
82 if (uint8Vec.size() % sizeof(uint16_t) != 0) {
83 return uint16Vec;
84 }
85 uint8_t lowByte;
86 uint8_t highByte;
87 uint16_t combined;
88 for (size_t i = 0; i < uint8Vec.size() - 1; i += sizeof(uint16_t)) {
89 /* 获取高位和低位字节 */
90 lowByte = uint8Vec[i];
91 highByte = uint8Vec[i + 1];
92 /* 合并成一个 uint16_t, 高位字节左移8位后与低位字节按位或 */
93 combined = (highByte << WifiDataConstants::AI_OFFSET_8) | lowByte;
94 /* 添加到 uint16_t 向量中 */
95 uint16Vec.push_back(combined);
96 }
97 return uint16Vec;
98 }
99
SequenceMerge(const std::vector<uint16_t> & sequence)100 std::vector<uint16_t> WifiDataReportService::SequenceMerge(const std::vector<uint16_t>& sequence)
101 {
102 std::vector<uint16_t> mergeSequence(WifiDataConstants::CDF_LAST_LEN, 0);
103 if (sequence.size() != WifiDataConstants::CDF_PROCESS_LEN) {
104 WIFI_LOGE("sequence should have exactly 32 elements.");
105 return mergeSequence;
106 }
107 int index = 0;
108 /* BE */
109 std::vector<uint16_t> cdfBe;
110 cdfBe.insert(cdfBe.end(), sequence.begin() + index, sequence.begin() + index + WifiDataConstants::CDF_LAST_LEN);
111 index = index + WifiDataConstants::CDF_LAST_LEN;
112 /* BK */
113 std::vector<uint16_t> cdfBk;
114 cdfBk.insert(cdfBk.end(), sequence.begin() + index, sequence.begin() + index + WifiDataConstants::CDF_LAST_LEN);
115 index = index + WifiDataConstants::CDF_LAST_LEN;
116 /* VI */
117 std::vector<uint16_t> cdfVi;
118 cdfVi.insert(cdfVi.end(), sequence.begin() + index, sequence.begin() + index + WifiDataConstants::CDF_LAST_LEN);
119 index = index + WifiDataConstants::CDF_LAST_LEN;
120 /* VO */
121 std::vector<uint16_t> cdfVo;
122 cdfVo.insert(cdfVo.end(), sequence.begin() + index, sequence.begin() + index + WifiDataConstants::CDF_LAST_LEN);
123
124 for (size_t i = 0; i < cdfBe.size(); i++) {
125 mergeSequence[i] = cdfBe[i] + cdfBk[i] + cdfVi[i] + cdfVo[i];
126 }
127 return mergeSequence;
128 }
129
GetApDeviceInfo(const int & networkId,int instId,WifiDeviceConfig & apDeviceInfo)130 void WifiDataReportService::GetApDeviceInfo(const int& networkId, int instId, WifiDeviceConfig& apDeviceInfo)
131 {
132 if (WifiSettings::GetInstance().GetDeviceConfig(networkId, apDeviceInfo, instId) != 0) {
133 WIFI_LOGE("ReportApConnEventInfo GetDeviceConfig failed!");
134 return;
135 }
136 }
137
UpdateApConnEventTimepInfo(ConnTimeType timeType)138 void WifiDataReportService::UpdateApConnEventTimepInfo(ConnTimeType timeType)
139 {
140 switch (timeType) {
141 case ConnTimeType::STA_CONN_START:
142 connEventTimepInfo_.timepConnStart = std::time(nullptr);
143 break;
144 case ConnTimeType::STA_DHCP_SUC:
145 connEventTimepInfo_.timepDhcpSuc = std::time(nullptr);
146 connEventTimepInfo_.timeToSucConn =
147 connEventTimepInfo_.timepDhcpSuc - connEventTimepInfo_.timepConnStart;
148 break;
149 case ConnTimeType::STA_DISCONN_SUC:
150 connEventTimepInfo_.timepDisconnSuc = std::time(nullptr);
151 connEventTimepInfo_.timeToDuraConn =
152 connEventTimepInfo_.timepDisconnSuc - connEventTimepInfo_.timepDhcpSuc;
153 break;
154 default:
155 break;
156 }
157 }
158
IsAdjacentChannel(int apFrequency,int targetApFrequency,char wifiBand)159 bool WifiDataReportService::IsAdjacentChannel(int apFrequency, int targetApFrequency, char wifiBand)
160 {
161 int channelWidth = wifiBand == 1 ? WifiDataConstants::CHANNEL_WIDTH_2_4G : WifiDataConstants::CHANNEL_WIDTH_5G;
162
163 return std::abs(targetApFrequency - apFrequency) <= channelWidth;
164 }
165
UpdateSameAdjaFreqCount(WifiCrowdsourcedDetailInfo & apDetailInfo,const std::string targetBssid,const int freq,const int band)166 void WifiDataReportService::UpdateSameAdjaFreqCount(WifiCrowdsourcedDetailInfo& apDetailInfo,
167 const std::string targetBssid, const int freq, const int band)
168 {
169 int apSamefreqCount = 0;
170 int apAdjafreqCount = 0;
171
172 /* 获取扫描结果并判空 */
173 std::vector<WifiScanInfo> scanResults;
174 WifiConfigCenter::GetInstance().GetWifiScanConfig()->GetScanInfoList(scanResults);
175 if (scanResults.empty()) {
176 WIFI_LOGE("scanResults is empty");
177 return;
178 }
179
180 /* 计算同频邻频ap数 */
181 for (WifiScanInfo& result : scanResults) {
182 if (result.bssid.empty()) {
183 continue;
184 }
185 if (result.bssid == targetBssid) {
186 continue;
187 }
188 if (result.frequency == freq) {
189 apSamefreqCount++;
190 continue;
191 }
192 if (IsAdjacentChannel(freq, result.frequency, band)) {
193 apAdjafreqCount++;
194 }
195 }
196
197 apDetailInfo.apSamefreq = apSamefreqCount;
198 apDetailInfo.apAdjafreq = apAdjafreqCount;
199 }
200
UpdateForegroundBundleName(WifiCrowdsourcedDetailInfo & apDetailInfo)201 void WifiDataReportService::UpdateForegroundBundleName(WifiCrowdsourcedDetailInfo& apDetailInfo)
202 {
203 StaStateMachine* staStateMachinePtr = GetStaStateMachine();
204 if (staStateMachinePtr == nullptr) {
205 WIFI_LOGE("Failed to get staStateMachinePtr.");
206 return;
207 }
208 apDetailInfo.appName = staStateMachinePtr->curForegroundAppBundleName_;
209 }
210
UpdateCrowdsourcedDetailInfo(WifiCrowdsourcedDetailInfo & apDetailInfo,const WifiLinkedInfo & linkedInfo,const WifiDeviceConfig & apDeviceInfo)211 void WifiDataReportService::UpdateCrowdsourcedDetailInfo(WifiCrowdsourcedDetailInfo& apDetailInfo,
212 const WifiLinkedInfo& linkedInfo, const WifiDeviceConfig& apDeviceInfo)
213 {
214 /* 更新上报时间 */
215 apDetailInfo.reporTimeStamp = std::time(nullptr);
216
217 /* 更新 link 和 device 信息 */
218 apDetailInfo.lastHasInternetTime = apDeviceInfo.lastHasInternetTime;
219 apDetailInfo.connFailedCount = apDeviceInfo.connFailedCount;
220 apDetailInfo.isPortal = apDeviceInfo.isPortal;
221 apDetailInfo.apKeyMgmt = apDeviceInfo.keyMgmt;
222 apDetailInfo.band = apDeviceInfo.band;
223 apDetailInfo.frequency = apDeviceInfo.frequency;
224 apDetailInfo.rssi = linkedInfo.rssi;
225 apDetailInfo.ssid = linkedInfo.ssid;
226 apDetailInfo.bssid = linkedInfo.bssid;
227 apDetailInfo.channelWidth = linkedInfo.channelWidth;
228 apDetailInfo.isHiddenSSID = linkedInfo.ifHiddenSSID;
229 apDetailInfo.wifiStandard = linkedInfo.wifiStandard;
230 apDetailInfo.maxSupportedRxLinkSpeed = linkedInfo.maxSupportedRxLinkSpeed;
231 apDetailInfo.maxSupportedTxLinkSpeed = linkedInfo.maxSupportedTxLinkSpeed;
232 apDetailInfo.supportedWifiCategory = linkedInfo.supportedWifiCategory;
233 apDetailInfo.isMloConnected = linkedInfo.isMloConnected;
234 apDetailInfo.apMobile = linkedInfo.isDataRestricted; // 通过数据流量限制判断热点是否为手机连接
235 apDetailInfo.timeToDuraConn = connEventTimepInfo_.timeToDuraConn;
236 apDetailInfo.timeToSucConn = connEventTimepInfo_.timeToSucConn;
237
238 /* 更新前台应用包名 */
239 UpdateForegroundBundleName(apDetailInfo);
240
241 /* 更新同频 ap 和邻频 ap 数 */
242 UpdateSameAdjaFreqCount(apDetailInfo, linkedInfo.bssid, linkedInfo.frequency, linkedInfo.band);
243 }
244
245
ParseSignalPollInfo(WifiCrowdsourcedQoeInfo & parseInfo,const WifiSignalPollInfo & signalPollInfo)246 void WifiDataReportService::ParseSignalPollInfo(WifiCrowdsourcedQoeInfo& parseInfo,
247 const WifiSignalPollInfo& signalPollInfo)
248 {
249 /* 填充 QoeInfo 字段 */
250 parseInfo.txRate = signalPollInfo.txrate;
251 parseInfo.rxRate = signalPollInfo.rxrate;
252 parseInfo.noise = signalPollInfo.noise;
253 parseInfo.txPackets = signalPollInfo.txPackets;
254 parseInfo.rxPackets = signalPollInfo.rxPackets;
255 parseInfo.snr = signalPollInfo.snr;
256 parseInfo.chload = signalPollInfo.chload;
257 parseInfo.txBytes = signalPollInfo.txBytes;
258 parseInfo.rxBytes = signalPollInfo.rxBytes;
259 parseInfo.txFailed = signalPollInfo.txFailed;
260 parseInfo.chloadSelf = signalPollInfo.chloadSelf;
261 ParseSignalPollInfoEx(parseInfo, signalPollInfo); // 解析SignalPoll.Ext中的信息
262 }
263
ParseSignalPollInfoEx(WifiCrowdsourcedQoeInfo & parseInfo,const WifiSignalPollInfo & signalPollInfo)264 void WifiDataReportService::ParseSignalPollInfoEx(WifiCrowdsourcedQoeInfo& parseInfo,
265 const WifiSignalPollInfo& signalPollInfo)
266 {
267 std::vector<uint8_t> signalPollInfoVec = signalPollInfo.ext;
268 if (signalPollInfoVec.size() < WifiDataConstants::QOE_INFO_LEN) {
269 return;
270 }
271 size_t index = 0;
272 index = index + WifiDataConstants::BEACON_RSSI_LEN; // 跳过 beacon rssi
273 parseInfo.txPpduCnt = GetUint32FromExt(signalPollInfoVec, index); // BadApTxPpduCnt
274
275 index = index + sizeof(uint32_t);
276 parseInfo.txPpduRetryCnt = GetUint32FromExt(signalPollInfoVec, index); // BadApTxPpduRetryCnt
277
278 index = index + sizeof(uint32_t);
279 parseInfo.txMcs = signalPollInfoVec[index]; // BadApTxMcs
280
281 index = index + 1 + WifiDataConstants::AI_CW_LEN; // jump cw
282 std::vector<uint8_t> uldelayCdfUint8; // uldelay 序列
283 std::vector<uint16_t> uldelayCdfUint16;
284 uldelayCdfUint8.insert(uldelayCdfUint8.end(),
285 signalPollInfoVec.begin() + index, signalPollInfoVec.begin() + index + WifiDataConstants::CDF_RAW_LEN);
286 uldelayCdfUint16 = ConvertUint8ToUint16(uldelayCdfUint8);
287
288 index = index + WifiDataConstants::CDF_RAW_LEN;
289 std::vector<uint8_t> txTimeCdfUint8; // txtime 序列
290 std::vector<uint16_t> txTimeCdfUint16;
291 txTimeCdfUint8.insert(txTimeCdfUint8.end(),
292 signalPollInfoVec.begin() + index, signalPollInfoVec.begin() + index + WifiDataConstants::CDF_RAW_LEN);
293 txTimeCdfUint16 = ConvertUint8ToUint16(txTimeCdfUint8);
294 /* 合并序列 */
295 std::vector<uint16_t> ulDelayCdf = SequenceMerge(uldelayCdfUint16);
296 std::vector<uint16_t> txTimeCdf = SequenceMerge(txTimeCdfUint16);
297
298 parseInfo.ulDelayCdf = ulDelayCdf;
299 parseInfo.txTimeCdf = txTimeCdf;
300 }
301
UpdateCrowdsourcedQoeInfo(WifiCrowdsourcedQoeInfo & apQoeInfo,const std::vector<WifiCrowdsourcedQoeInfo> & historyData)302 void WifiDataReportService::UpdateCrowdsourcedQoeInfo(WifiCrowdsourcedQoeInfo& apQoeInfo,
303 const std::vector<WifiCrowdsourcedQoeInfo>& historyData)
304 {
305 /* 累加 */
306 for (const auto& info : historyData) {
307 apQoeInfo.txRate += info.txRate;
308 apQoeInfo.rxRate += info.rxRate;
309 apQoeInfo.noise += info.noise;
310 apQoeInfo.txPackets += info.txPackets;
311 apQoeInfo.rxPackets += info.rxPackets;
312 apQoeInfo.snr += info.snr;
313 apQoeInfo.chload += info.chload;
314 apQoeInfo.txBytes = (apQoeInfo.txBytes > INT_MAX - info.txBytes) ? INT_MAX : apQoeInfo.txBytes + info.txBytes;
315 apQoeInfo.rxBytes = (apQoeInfo.rxBytes > INT_MAX - info.rxBytes) ? INT_MAX : apQoeInfo.rxBytes + info.rxBytes;
316 apQoeInfo.txFailed += info.txFailed;
317 apQoeInfo.chloadSelf += info.chloadSelf;
318 apQoeInfo.txPpduCnt += info.txPpduCnt;
319 apQoeInfo.txPpduRetryCnt += info.txPpduRetryCnt;
320 apQoeInfo.txMcs = info.txMcs;
321 }
322
323 /* 计算均值 */
324 apQoeInfo.txRate /= WifiDataConstants::MAX_PUSH_COUNT;
325 apQoeInfo.rxRate /= WifiDataConstants::MAX_PUSH_COUNT;
326 apQoeInfo.noise /= WifiDataConstants::MAX_PUSH_COUNT;
327 apQoeInfo.txPackets /= WifiDataConstants::MAX_PUSH_COUNT;
328 apQoeInfo.rxPackets /= WifiDataConstants::MAX_PUSH_COUNT;
329 apQoeInfo.snr /= WifiDataConstants::MAX_PUSH_COUNT;
330 apQoeInfo.chload /= WifiDataConstants::MAX_PUSH_COUNT;
331 apQoeInfo.txBytes /= WifiDataConstants::MAX_PUSH_COUNT;
332 apQoeInfo.rxBytes /= WifiDataConstants::MAX_PUSH_COUNT;
333 apQoeInfo.txFailed /= WifiDataConstants::MAX_PUSH_COUNT;
334 apQoeInfo.chloadSelf /= WifiDataConstants::MAX_PUSH_COUNT;
335 apQoeInfo.txPpduCnt /= WifiDataConstants::MAX_PUSH_COUNT;
336 apQoeInfo.txPpduRetryCnt /= WifiDataConstants::MAX_PUSH_COUNT;
337 apQoeInfo.txMcs /= WifiDataConstants::MAX_PUSH_COUNT;
338
339 /* 处理 vector 型数据,将每个 vector 中的元素相加 */
340 apQoeInfo.ulDelayCdf.resize(WifiDataConstants::CDF_LAST_LEN, 0); // 调整 mergedInfo.ulDelayCdf 的大小并初始化其元素为 0
341 apQoeInfo.txTimeCdf.resize(WifiDataConstants::CDF_LAST_LEN, 0); // 调整 mergedInfo.txTimeCdf 的大小并初始化其元素为 0
342
343 /* 合并 ulDelayCdf, txTimeCdf */
344 for (const auto& info : historyData) {
345 if (info.ulDelayCdf.size() < WifiDataConstants::CDF_LAST_LEN ||
346 info.txTimeCdf.size() < WifiDataConstants::CDF_LAST_LEN) {
347 return;
348 }
349
350 for (size_t i = 0; i < WifiDataConstants::CDF_LAST_LEN; ++i) {
351 apQoeInfo.ulDelayCdf[i] += info.ulDelayCdf[i];
352 apQoeInfo.txTimeCdf[i] += info.txTimeCdf[i];
353 }
354 }
355 }
356
357 /* 事件上报 */
ReportApConnEventInfo(ConnReportReason reportReason,int targetNetworkId)358 void WifiDataReportService::ReportApConnEventInfo(ConnReportReason reportReason, int targetNetworkId)
359 {
360 std::lock_guard<std::mutex> lock(historyMutex_);
361 /* 检查断连标志位 */
362 if (disConnFlag_) {
363 return;
364 }
365
366 StaStateMachine* staStateMachinePtr = GetStaStateMachine();
367 if (staStateMachinePtr == nullptr) {
368 WIFI_LOGE("Failed to get staStateMachinePtr.");
369 return;
370 }
371
372 /* 获取 Ap deviece 信息 */
373 WifiDeviceConfig apDeviceInfo;
374 GetApDeviceInfo(targetNetworkId, staStateMachinePtr->m_instId, apDeviceInfo);
375
376 /* 根据连接原因更改对应设置 */
377 switch (reportReason) {
378 case ConnReportReason::CONN_SUC_START: // 更新连接成功时间, 不改变标志位 disConnFlag_
379 UpdateApConnEventTimepInfo(ConnTimeType::STA_DHCP_SUC);
380 break;
381 case ConnReportReason::CONN_DISCONNECTED: // 更新正常断开连接时间, 改变标志位 disConnFlag_
382 UpdateApConnEventTimepInfo(ConnTimeType::STA_DISCONN_SUC);
383 disConnFlag_ = true;
384 break;
385 case ConnReportReason::CONN_ASSOCIATION_REJECTION: // 关联拒绝, 改变标志位 disConnFlag_
386 case ConnReportReason::CONN_ASSOCIATION_FULL: // 接入点满, 改变标志位 disConnFlag_
387 if (apDeviceInfo.connFailedCount < WifiDataConstants::CONN_FAILED_COUNT_THRESHOLD) {
388 disConnFlag_ = true;
389 return;
390 }
391 [[fallthrough]];
392 case ConnReportReason::CONN_WRONG_PASSWORD: // 密码错误, 改变标志位 disConnFlag_
393 case ConnReportReason::CONN_AUTHENTICATION_FAILURE: // 认证失败, 改变标志位 disConnFlag_
394 case ConnReportReason::CONN_DHCP_FAILURE: // Dhcp 失败, 改变标志位 disConnFlag_
395 disConnFlag_ = true;
396 break;
397 default:
398 break;
399 }
400 /* 调用众包接口 */
401 WifiCrowdsourcedInfo wifiCrowdsourcedInfo;
402 wifiCrowdsourcedInfo.apDetailInfo.reason = reportReason;
403 UpdateCrowdsourcedDetailInfo(wifiCrowdsourcedInfo.apDetailInfo, staStateMachinePtr->linkedInfo, apDeviceInfo);
404 if (staStateMachinePtr->enhanceService_ == nullptr || wifiCrowdsourcedInfo.apDetailInfo.ssid.empty()) {
405 return;
406 }
407 staStateMachinePtr->enhanceService_->CrowdsourcedDataReportInterface(wifiCrowdsourcedInfo);
408 }
409
410 /* 周期上报 */
ReportQoeInfo(const WifiSignalPollInfo & signalPollInfo,ConnReportReason reportReason,int targetNetworkId)411 void WifiDataReportService::ReportQoeInfo(const WifiSignalPollInfo& signalPollInfo, ConnReportReason reportReason,
412 int targetNetworkId)
413 {
414 std::lock_guard<std::mutex> lock(historyMutex_);
415 StaStateMachine* staStateMachinePtr = GetStaStateMachine();
416 if (staStateMachinePtr == nullptr) {
417 WIFI_LOGE("Failed to get staStateMachinePtr.");
418 return;
419 }
420
421 time_t now = std::time(nullptr);
422 auto it = lastPushTime_.find(staStateMachinePtr->linkedInfo.bssid);
423 time_t lastPush;
424 if (it != lastPushTime_.end()) {
425 /* 非第一次上报 qoe */
426 lastPush = it->second; // 已存在,直接引用
427 } else {
428 /* 第一次上报 qoe */
429 lastPushTime_[staStateMachinePtr->linkedInfo.bssid] = 0;
430 lastPush = lastPushTime_[staStateMachinePtr->linkedInfo.bssid];
431 }
432
433 /* 是否第一次上报或者距离上次上报间隔是否超过 DELAY_TIME */
434 if (lastPush != 0 && now - lastPush < WifiDataConstants::DELAY_TIME) {
435 return;
436 }
437
438 WifiCrowdsourcedQoeInfo parseInfo;
439 ParseSignalPollInfo(parseInfo, signalPollInfo);
440 historyData_.push_back(parseInfo);
441
442 if (historyData_.size() >= WifiDataConstants::MAX_PUSH_COUNT) {
443 WifiCrowdsourcedInfo wifiCrowdsourcedInfo;
444 wifiCrowdsourcedInfo.apDetailInfo.reason = reportReason;
445
446 /* 获取 Ap deviece 信息 */
447 WifiDeviceConfig apDeviceInfo;
448 GetApDeviceInfo(targetNetworkId, staStateMachinePtr->m_instId, apDeviceInfo);
449
450 UpdateCrowdsourcedDetailInfo(wifiCrowdsourcedInfo.apDetailInfo, // 更新 link 和 device 信息
451 staStateMachinePtr->linkedInfo, apDeviceInfo);
452
453 UpdateCrowdsourcedQoeInfo(wifiCrowdsourcedInfo.apQoeInfo, historyData_); // 融合历史数据,更新 qoe 信息
454 historyData_.clear();
455
456 if (staStateMachinePtr->enhanceService_ == nullptr) {
457 return;
458 }
459 staStateMachinePtr->enhanceService_->CrowdsourcedDataReportInterface(wifiCrowdsourcedInfo);
460 lastPushTime_[staStateMachinePtr->linkedInfo.bssid] = std::time(nullptr);
461 }
462 }
463
464 } // namespace Wifi
465 } // namespace OHOS