当前位置: 首页 > news >正文

鸿蒙 WiFi 扫描流程(1)

上一篇记录了WiFi 的打开流程,这里我们继续看,WiFi使能后,如何发起扫描?代码还是用的 鸿蒙OpenHarmony4.0基线代码。

foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c

WifiErrorNo Start(void)
{LOGI("Ready to start wifi");if (StartSupplicant() != WIFI_HAL_SUCCESS) {LOGE("wpa_supplicant start failed!");return WIFI_HAL_OPEN_SUPPLICANT_FAILED;}LOGI("wpa_supplicant start successfully!");if (AddWpaIface(0) != WIFI_HAL_SUCCESS) {LOGE("Failed to add wpa interface!");StopWpaAndWpaHal(0);return WIFI_HAL_CONN_SUPPLICANT_FAILED;}if (ConnectSupplicant() != WIFI_HAL_SUCCESS) {LOGE("SupplicantHal connect wpa_supplicant failed!");StopWpaAndWpaHal(0);return WIFI_HAL_CONN_SUPPLICANT_FAILED;}
#ifdef HDI_INTERFACE_SUPPORTif (HdiStart() != WIFI_HAL_SUCCESS) {LOGE("[STA] Start hdi failed!");return WIFI_HAL_FAILED;}if (RegisterHdiStaCallbackEvent() != WIFI_HAL_SUCCESS) {LOGE("[STA] Start RegisterHdiStaCallbackEvent failed!");return WIFI_HAL_FAILED;}
#endifLOGI("Start wifi successfully");return WIFI_HAL_SUCCESS;
}

上段代码我们知道,如果使能成功后就会返回 WIFI_HAL_SUCCESS,那看下那个地方去判断这个返回值,这里的 WIFI_HAL_SUCCESS 值是 0,表示 Success;
foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_state_machine.cpp

void StaStateMachine::StartWifiProcess()
{WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::ENABLING));staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_OPENING);int res;if (WifiOprMidState::RUNNING == WifiConfigCenter::GetInstance().GetWifiScanOnlyMidState()) {res = static_cast<int>(WIFI_IDL_OPT_OK);} else {res = WifiStaHalInterface::GetInstance().StartWifi();     ---> 此时成功后,返回值是 0}if (res == static_cast<int>(WIFI_IDL_OPT_OK)) {    ---> 就走到这里来了WIFI_LOGI("Start wifi successfully!");if (WifiStaHalInterface::GetInstance().WpaAutoConnect(false) != WIFI_IDL_OPT_OK) {WIFI_LOGI("The automatic Wpa connection is disabled failed.");}/* callback the InterfaceService that wifi is enabled successfully. */        ---> 通知给相应的接口服务WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::ENABLED));staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_SUCCEED);/* Sets the MAC address of WifiSettings. */std::string mac;if ((WifiStaHalInterface::GetInstance().GetStaDeviceMacAddress(mac)) == WIFI_IDL_OPT_OK) {WifiSettings::GetInstance().SetMacAddress(mac);std::string realMacAddress;WifiSettings::GetInstance().GetRealMacAddress(realMacAddress);if (realMacAddress.empty()) {WifiSettings::GetInstance().SetRealMacAddress(mac);}} else {WIFI_LOGI("GetStaDeviceMacAddress failed!");}
#ifndef OHOS_ARCH_LITEWIFI_LOGI("Register netsupplier");WifiNetAgent::GetInstance().OnStaMachineWifiStart();
#endif/* Initialize Connection Information. */InitWifiLinkedInfo();InitLastWifiLinkedInfo();WifiSettings::GetInstance().SaveLinkedInfo(linkedInfo);SyncDeviceConfigToWpa();
#ifndef OHOS_ARCH_LITEChipCapability::GetInstance().InitializeChipCapability();
#endif/* The current state of StaStateMachine transfers to SeparatedState after* enable supplicant.*/SwitchState(pSeparatedState);      ---> 切换状态机} else {/* Notify the InterfaceService that wifi is failed to enable wifi. */LOGE("StartWifi failed, and errcode is %d.", res);WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::DISABLED));WifiSettings::GetInstance().SetUserLastSelectedNetworkId(INVALID_NETWORK_ID);staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_FAILED);}
}

这里我们看如何callback 的

// 更新状态
WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::ENABLED));
// 主要找到 staCallback 里面的 OnStaOpenRes 方法
staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_SUCCEED);
// 我们看下这个staCallback 是何时被赋值的,在 sta_state_machine.cpp 类里面找到如下:
void StaStateMachine::RegisterStaServiceCallback(const StaServiceCallback &callbacks)
{WIFI_LOGI("RegisterStaServiceCallback.");staCallback = callbacks;
}
// 那何时注册的呢?在往回找:
//foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_service.cpp
ErrCode StaService::InitStaService(const StaServiceCallback &callbacks)
{RegisterStaServiceCallback(callbacks);
}
void StaService::RegisterStaServiceCallback(const StaServiceCallback &callbacks) const
{LOGI("Enter StaService::RegisterStaServiceCallback.");if (pStaStateMachine == nullptr) {LOGE("pStaStateMachine is null.\n");return;}pStaStateMachine->RegisterStaServiceCallback(callbacks);    ---> 注册到上面的  sta_state_machine.cpp 类里面
}
// 再往回找,看谁调用StaService::InitStaService 方法,这里我就省去流程了,最终可以发现在 wifi_manager.cpp 类里面
// 传的参数都是  WifiManager::GetInstance().GetStaCallback(),所以直接看WifiManager里面的GetStaCallback方法
StaServiceCallback WifiManager::GetStaCallback()
{return mStaCallback;       ---> 就是这个
}// staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_SUCCEED); 也就是回掉WifiManager::mStaCallback::OnStaOpenRes方法
// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_manager.cpp
void WifiManager::InitStaCallback(void)
{mStaCallback.OnStaOpenRes = DealStaOpenRes;      ---》 初始化成这个,那我们就看这个mStaCallback.OnStaCloseRes = DealStaCloseRes;mStaCallback.OnStaConnChanged = DealStaConnChanged;mStaCallback.OnWpsChanged = DealWpsChanged;mStaCallback.OnStaStreamChanged = DealStreamChanged;mStaCallback.OnStaRssiLevelChanged = DealRssiChanged;return;
}
// OPEN_WIFI_SUCCEED 值是 1
void WifiManager::DealStaOpenRes(OperateResState state)
{   //  OPEN_WIFI_OPENING = 0, OPEN_WIFI_SUCCEED = 1, OPEN_WIFI_FAILED = 2;WIFI_LOGI("Enter DealStaOpenRes: %{public}d", static_cast<int>(state));WifiEventCallbackMsg cbMsg;cbMsg.msgCode = WIFI_CBK_MSG_STATE_CHANGE;if (state == OperateResState::OPEN_WIFI_OPENING) {cbMsg.msgData = static_cast<int>(WifiState::ENABLING);WifiInternalEventDispatcher::GetInstance().AddBroadCastMsg(cbMsg);return;}if ((state == OperateResState::OPEN_WIFI_FAILED) || (state == OperateResState::OPEN_WIFI_DISABLED)) {WIFI_LOGE("DealStaOpenRes:wifi open failed!");WifiConfigCenter::GetInstance().SetWifiMidState(WifiOprMidState::OPENING, WifiOprMidState::CLOSED);DealStaCloseRes(state);return;}WIFI_LOGI("DealStaOpenRes:wifi open successfully!");WifiConfigCenter::GetInstance().SetWifiMidState(WifiOprMidState::OPENING, WifiOprMidState::RUNNING);WifiConfigCenter::GetInstance().SetStaLastRunState(true);if (WifiConfigCenter::GetInstance().GetAirplaneModeState() == MODE_STATE_OPEN) {WifiConfigCenter::GetInstance().SetWifiStateWhenAirplaneMode(true);}
#ifdef FEATURE_P2P_SUPPORTWifiOprMidState p2pState = WifiConfigCenter::GetInstance().GetP2pMidState();WIFI_LOGI("DealStaOpenRes, current p2p state:%{public}d", p2pState);if (p2pState == WifiOprMidState::CLOSED) {WifiManager::GetInstance().AutoStartP2pService(AutoStartOrStopServiceReason::TYRTO_ENABLE_P2P_WHEN_WIFI_OPENED);}
#endifcbMsg.msgData = static_cast<int>(WifiState::ENABLED);WifiInternalEventDispatcher::GetInstance().AddBroadCastMsg(cbMsg);AutoStartEnhanceService();CheckAndStartScanService();    ---> 和扫描相关的if (WifiSettings::GetInstance().CheckScanOnlyAvailable() &&WifiManager::GetInstance().GetLocationModeByDatashare(WIFI_SCAN_ABILITY_ID)) {WifiConfigCenter::GetInstance().SetWifiScanOnlyMidState(WifiOprMidState::RUNNING);}
}// 看扫描相关的 CheckAndStartScanService 方法:
void WifiManager::CheckAndStartScanService(void)
{WifiOprMidState scanState = WifiConfigCenter::GetInstance().GetScanMidState();WIFI_LOGI("CheckAndStartScanService scanState: %{public}d", static_cast<int>(scanState));if (scanState != WifiOprMidState::CLOSED) {/* If the scanning function is enabled when the STA is not enabled, you need to start the scheduledscanning function immediately when the STA is enabled. */IScanService *pService = WifiServiceManager::GetInstance().GetScanServiceInst();if (pService != nullptr) {pService->OnClientModeStatusChanged(static_cast<int>(OperateResState::DISCONNECT_DISCONNECTED));}return;}if (!WifiConfigCenter::GetInstance().SetScanMidState(scanState, WifiOprMidState::OPENING)) {WIFI_LOGW("Failed to set scan mid state opening! may be other activity has been operated");return;}ErrCode errCode = WIFI_OPT_FAILED;do {if (WifiServiceManager::GetInstance().CheckAndEnforceService(WIFI_SERVICE_SCAN) < 0) {WIFI_LOGE("Load %{public}s service failed!", WIFI_SERVICE_SCAN);break;}IScanService *pService = WifiServiceManager::GetInstance().GetScanServiceInst();    ---> 这个就是scan_interface.cppif (pService == nullptr) {WIFI_LOGE("Create %{public}s service failed!", WIFI_SERVICE_SCAN);break;}errCode = pService->RegisterScanCallbacks(WifiManager::GetInstance().GetScanCallback());if (errCode != WIFI_OPT_SUCCESS) {WIFI_LOGE("Register scan service callback failed!");break;}errCode = pService->Init();     ----> 主要看下这个if (errCode != WIFI_OPT_SUCCESS) {WIFI_LOGE("init scan service failed, ret %{public}d!", static_cast<int>(errCode));break;}IEnhanceService *pEnhanceService = WifiServiceManager::GetInstance().GetEnhanceServiceInst();if (pEnhanceService == nullptr) {WIFI_LOGE("Create %{public}s service failed!", WIFI_SERVICE_ENHANCE);break;}errCode = pService->SetEnhanceService(pEnhanceService);if (errCode != WIFI_OPT_SUCCESS) {WIFI_LOGE("SetEnhanceService failed, ret %{public}d!", static_cast<int>(errCode));break;}} while (0);if (errCode != WIFI_OPT_SUCCESS) {WifiConfigCenter::GetInstance().SetScanMidState(WifiOprMidState::OPENING, WifiOprMidState::CLOSED);WifiServiceManager::GetInstance().UnloadService(WIFI_SERVICE_SCAN);}return;
}

pService->Init() 看下初始化扫描服务foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_interface.cpp

ErrCode ScanInterface::Init()
{WIFI_LOGI("Enter ScanInterface::Init.\n");pScanService = new (std::nothrow)ScanService();     ---> 创建可一个 ScanService,初始化参数if (pScanService == nullptr) {WIFI_LOGE("New ScanService failed.\n");return WIFI_OPT_INVALID_PARAM;}if (!(pScanService->InitScanService(mScanSerivceCallbacks))) {   ---> 对应上面传下来的注册参数WIFI_LOGE("InitScanService failed.\n");delete pScanService;pScanService = nullptr;return WIFI_OPT_INVALID_PARAM;}return WIFI_OPT_SUCCESS;
}//foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cpp
bool ScanService::InitScanService(const IScanSerivceCallbacks &scanSerivceCallbacks)
{WIFI_LOGI("Enter ScanService::InitScanService.\n");mScanSerivceCallbacks = scanSerivceCallbacks;pScanStateMachine = new (std::nothrow) ScanStateMachine();    ---> 状态机if (pScanStateMachine == nullptr) {WIFI_LOGE("Alloc pScanStateMachine failed.\n");return false;}if (!pScanStateMachine->InitScanStateMachine()) {WIFI_LOGE("InitScanStateMachine failed.\n");return false;}if (!pScanStateMachine->EnrollScanStatusListener(std::bind(&ScanService::HandleScanStatusReport, this, std::placeholders::_1))) {WIFI_LOGE("ScanStateMachine_->EnrollScanStatusListener failed.\n");return false;}pScanMonitor = new (std::nothrow) ScanMonitor();     ---> 消息监视if (pScanMonitor == nullptr) {WIFI_LOGE("Alloc pScanMonitor failed.\n");return false;}if (!pScanMonitor->InitScanMonitor()) {WIFI_LOGE("InitScanMonitor failed.\n");return false;}
#ifndef OHOS_ARCH_LITEif (standByListerner.Init()) {WIFI_LOGE("standByListerner Init failed.");}
#endifif ((WifiStaHalInterface::GetInstance().GetSupportFrequencies(SCAN_BAND_24_GHZ, freqs2G) != WIFI_IDL_OPT_OK) ||(WifiStaHalInterface::GetInstance().GetSupportFrequencies(SCAN_BAND_5_GHZ, freqs5G) != WIFI_IDL_OPT_OK) ||(WifiStaHalInterface::GetInstance().GetSupportFrequencies(SCAN_BAND_5_GHZ_DFS_ONLY, freqsDfs) !=WIFI_IDL_OPT_OK)) {WIFI_LOGE("GetSupportFrequencies failed.\n");}ChannelsTable chanTbs;(void)WifiSettings::GetInstance().GetValidChannels(chanTbs);if (chanTbs[BandType::BAND_2GHZ].size() == 0) {WIFI_LOGI("Update valid channels!");std::vector<int32_t> supp2Gfreqs(freqs2G.begin(), freqs2G.end());std::vector<int32_t> supp5Gfreqs(freqs5G.begin(), freqs5G.end());for (auto iter = supp2Gfreqs.begin(); iter != supp2Gfreqs.end(); iter++) {int32_t channel = FrequencyToChannel(*iter);if (channel == INVALID_FREQ_OR_CHANNEL) {continue;}chanTbs[BandType::BAND_2GHZ].push_back(channel);}for (auto iter = supp5Gfreqs.begin(); iter != supp5Gfreqs.end(); iter++) {int32_t channel = FrequencyToChannel(*iter);if (channel == INVALID_FREQ_OR_CHANNEL) {continue;}chanTbs[BandType::BAND_5GHZ].push_back(channel);}if (WifiSettings::GetInstance().SetValidChannels(chanTbs)) {WIFI_LOGE("%{public}s, fail to SetValidChannels", __func__);}}pScanMonitor->SetScanStateMachine(pScanStateMachine);pScanStateMachine->SendMessage(static_cast<int>(CMD_SCAN_PREPARE));    ---> 状态机里面处理 CMD_SCAN_PREPAREGetScanControlInfo();return true;
}

我们到状态机里面看下如何处理这个消息 CMD_SCAN_PREPARE
foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_state_machine.cpp

bool ScanStateMachine::InitState::ExecuteStateMsg(InternalMessage *msg)
{WIFI_LOGI("Enter ScanStateMachine::InitState::ExecuteStateMsg.\n");if (msg == nullptr) {WIFI_LOGE("msg is null.\n");return true;}switch (msg->GetMessageName()) {case CMD_SCAN_PREPARE:LoadDriver();   ---> 执行这个方法return true;// 看下LoadDriver() 方法:
void ScanStateMachine::InitState::LoadDriver()
{WIFI_LOGI("Enter ScanStateMachine::LoadDriver.\n");pScanStateMachine->SwitchState(pScanStateMachine->hardwareReadyState);   ---> 状态切换为 HardwareReadyStatepScanStateMachine->ReportStatusChange(SCAN_STARTED_STATUS);     ---> 上报 SCAN_STARTED_STATUS = 0,  /* Started successfully */WIFI_LOGI("Start Scan Service Success.\n");
}void ScanStateMachine::ReportStatusChange(ScanStatus status)
{WIFI_LOGI("Enter ScanStateMachine::ReportStatusChange.\n");ScanStatusReport scanStatusReport;scanStatusReport.status = status;if (scanStatusReportHandler) {scanStatusReportHandler(scanStatusReport);     ---> 看这个}
}
// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cpp
void ScanService::HandleScanStatusReport(ScanStatusReport &scanStatusReport)
{WIFI_LOGI("Enter ScanService::HandleScanStatusReport.\n");switch (scanStatusReport.status) {case SCAN_STARTED_STATUS: {if (pScanStateMachine == nullptr) {WIFI_LOGE("HandleScanStatusReport-SCAN_STARTED_STATUS pScanStateMachine is null\n");return;}scanStartedFlag = true;/* Pno scan maybe has started, stop it first. */pScanStateMachine->SendMessage(CMD_STOP_PNO_SCAN);    ---》 先停止PNO扫描mScanSerivceCallbacks.OnScanStartEvent();    ---> 更新下状态SystemScanProcess(true);    ---> 看这个方法break;}
// 跟着流程继续往下看: 
void ScanService::SystemScanProcess(bool scanAtOnce)
{WIFI_LOGI("Enter ScanService::SystemScanProcess, scanAtOnce:%{public}d.", scanAtOnce);StopSystemScan();int state = WifiSettings::GetInstance().GetScreenState();WIFI_LOGI("Screen state(1:OPEN, 2:CLOSE): %{public}d.", state);   ---> 屏幕状态决定哪种扫描模式if (state == MODE_STATE_OPEN) {{std::unique_lock<std::mutex> lock(scanControlInfoMutex);int i = 0;for (auto iter = scanControlInfo.scanIntervalList.begin(); iter != scanControlInfo.scanIntervalList.end(); ++iter) {if (iter->scanScene ==SCAN_SCENE_ALL && iter->scanMode ==ScanMode::SYSTEM_TIMER_SCAN && iter->isSingle ==false) {WIFI_LOGI("iter[%{public}d]: intervalMode:%{public}d, interval:%{public}d, count:%{public}d",i++, iter->intervalMode, iter->interval, iter->count);systemScanIntervalMode.scanIntervalMode.intervalMode = iter->intervalMode;systemScanIntervalMode.scanIntervalMode.interval = iter->interval;systemScanIntervalMode.scanIntervalMode.count = iter->count;systemScanIntervalMode.expScanCount = 0;}}}// 上面的参数配置好后,执行系统调度扫描StartSystemTimerScan(scanAtOnce);} else {if (!BeginPnoScan()) {WIFI_LOGE("BeginPnoScan failed.");return;}}return;
}

看下扫描模式有哪些,这里的是 SYSTEM_TIMER_SCAN

enum class ScanMode {APP_FOREGROUND_SCAN = 0, /* Scan initiated by the foreground application */APP_BACKGROUND_SCAN = 1, /* Scan initiated by background applications */SYS_FOREGROUND_SCAN = 2, /* System foreground scan */SYS_BACKGROUND_SCAN = 3, /* System background scan */ALL_EXTERN_SCAN = 4,     /* All external scans, including the first four */PNO_SCAN = 5,            /* PNO scan */SYSTEM_TIMER_SCAN = 6,   /* Scheduled system scan */ANYTIME_SCAN = 7,        /* Scan at any time */BAND_24GHZ_SCAN = 8,     /* 2.4 GHz scan */BAND_5GHZ_SCAN = 9,      /* 5G scan */SCAN_MODE_MAX            /* Invalid value */

接着看上面提到的这个方法: StartSystemTimerScan(scanAtOnce);

void ScanService::StartSystemTimerScan(bool scanAtOnce)
{WIFI_LOGI("Enter ScanService::StartSystemTimerScan, scanAtOnce: %{public}d.", scanAtOnce);ErrCode rlt = ApplyScanPolices(ScanType::SCAN_TYPE_SYSTEMTIMER);    ---> 决定是否允许以及如何对Wi-Fi进行扫描操作的一些判断if (rlt != WIFI_OPT_SUCCESS) {return;}struct timespec times = { 0, 0 };clock_gettime(CLOCK_MONOTONIC, &times);int64_t nowTime =static_cast<int64_t>(times.tv_sec) * SECOND_TO_MILLI_SECOND + times.tv_nsec / SECOND_TO_MICRO_SECOND;int sinceLastScan = 0;if (lastSystemScanTime != 0) {sinceLastScan = nowTime - lastSystemScanTime;}/** The scan is performed immediately, the first scan is required,* or the time since the last scan is longer than the scan interval.*/int scanTime = SYSTEM_SCAN_INIT_TIME;if (systemScanIntervalMode.scanIntervalMode.interval > 0) {scanTime = systemScanIntervalMode.scanIntervalMode.interval;}if (scanAtOnce || (lastSystemScanTime == 0) || (sinceLastScan >= systemScanIntervalMode.scanIntervalMode.interval)) {if (Scan(false) != WIFI_OPT_SUCCESS) {      ---> 发起扫描WIFI_LOGE("Scan failed.");}lastSystemScanTime = nowTime;} else {scanTime = systemScanIntervalMode.scanIntervalMode.interval - sinceLastScan;}// 上面都是对扫描时间的一些逻辑WIFI_LOGI("StartSystemTimerScan, scanTime: %{public}d,  interval:%{public}d,  count:%{public}d",scanTime,systemScanIntervalMode.scanIntervalMode.interval,systemScanIntervalMode.scanIntervalMode.count);pScanStateMachine->StartTimer(static_cast<int>(SYSTEM_SCAN_TIMER), scanTime * SECOND_TO_MILLI_SECOND);   ---》 启动一个定时器return;
}

两个参数,前者是实际的扫描时间,后者是最大的扫描时间,这里是10s
pScanStateMachine->StartTimer(static_cast(SYSTEM_SCAN_TIMER), scanTime * SECOND_TO_MILLI_SECOND);
继续看下发起的扫描 Scan(false)
foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cpp

ErrCode ScanService::Scan(bool externFlag)
{WIFI_LOGI("Enter ScanService::Scan, externFlag:%{public}d.\n", externFlag);      ---> 传下来的是falseif (!scanStartedFlag) {WIFI_LOGE("Scan service has not started.\n");return WIFI_OPT_FAILED;}if (externFlag) {      ---> 这里没有额外的ErrCode rlt = ApplyScanPolices(ScanType::SCAN_TYPE_EXTERN);if (rlt != WIFI_OPT_SUCCESS) {return rlt;}}ScanConfig scanConfig;/** Invoke the interface provided by the configuration center to obtain the* hidden network list.*/if (!GetHiddenNetworkSsidList(scanConfig.hiddenNetworkSsid)) {       ---> 发现是否有隐藏网络WIFI_LOGE("GetHiddenNetworkSsidList failed.\n");}scanConfig.scanBand = SCAN_BAND_BOTH_WITH_DFS;scanConfig.fullScanFlag = true;scanConfig.externFlag = externFlag;scanConfig.scanStyle = SCAN_TYPE_HIGH_ACCURACY;if (!SingleScan(scanConfig)) {                  ---> 发起单词扫描,这个和Android 扫描差不多     WIFI_LOGE("SingleScan failed.\n");return WIFI_OPT_FAILED;}return WIFI_OPT_SUCCESS;
}
// 继续看 发起单次扫描:
bool ScanService::SingleScan(ScanConfig &scanConfig)
{WIFI_LOGI("Enter ScanService::SingleScan.\n");#ifndef OHOS_ARCH_LITEif (!standByListerner.AllowScan()) {WIFI_LOGE("Scan not allowed when device in standby state.\n");return WIFI_OPT_FAILED;}
#endifGetAllowBandFreqsControlInfo(scanConfig.scanBand, scanConfig.scanFreqs);if ((scanConfig.scanBand == SCAN_BAND_UNSPECIFIED) && (scanConfig.scanFreqs.empty())) {WIFI_LOGE("Have no allowed band or freq.\n");return false;}InterScanConfig interConfig;interConfig.fullScanFlag = scanConfig.fullScanFlag;interConfig.hiddenNetworkSsid.assign(scanConfig.hiddenNetworkSsid.begin(), scanConfig.hiddenNetworkSsid.end());interConfig.scanStyle = scanConfig.scanStyle;/* Specified frequency */if (scanConfig.scanBand == SCAN_BAND_UNSPECIFIED) {interConfig.scanFreqs.assign(scanConfig.scanFreqs.begin(), scanConfig.scanFreqs.end());/** When band is SCAN_BAND_BOTH_WITH_DFS, need to scan all frequency,* scanFreqs can be empty.*/} else if (scanConfig.scanBand != SCAN_BAND_BOTH_WITH_DFS) {/* Converting frequency bands to frequencies. */if (!GetBandFreqs(scanConfig.scanBand, interConfig.scanFreqs)) {WIFI_LOGE("GetBandFreqs failed.\n");return false;}}/* Save the configuration. */int requestIndex = StoreRequestScanConfig(scanConfig, interConfig);if (requestIndex == MAX_SCAN_CONFIG_STORE_INDEX) {WIFI_LOGE("StoreRequestScanConfig failed.\n");return false;}std::unique_lock<std::mutex> lock(scanConfigMapMutex);if (pScanStateMachine == nullptr) {WIFI_LOGE("pScanStateMachine is null.\n");return false;}/* Construct a message. */InternalMessage *interMessage =pScanStateMachine->CreateMessage(static_cast<int>(CMD_START_COMMON_SCAN), requestIndex);if (interMessage == nullptr) {scanConfigMap.erase(requestIndex);WIFI_LOGE("CreateMessage failed.\n");return false;}if (!AddScanMessageBody(interMessage, interConfig)) {scanConfigMap.erase(requestIndex);MessageManage::GetInstance().ReclaimMsg(interMessage);WIFI_LOGE("AddScanMessageBody failed.\n");return false;}pScanStateMachine->SendMessage(interMessage);return true;
}

这篇文章先记录到这里,下篇文章接着 SingleScan 方法往下看,看如何和HAL交互。

相关文章:

鸿蒙 WiFi 扫描流程(1)

上一篇记录了WiFi 的打开流程&#xff0c;这里我们继续看&#xff0c;WiFi使能后&#xff0c;如何发起扫描&#xff1f;代码还是用的 鸿蒙OpenHarmony4.0基线代码。 foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c WifiError…...

基于YOLOv8的暗光低光环境下(ExDark数据集)检测,加入多种优化方式---DCNv4结合SPPF ,助力自动驾驶(一)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了暗光低光数据集检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析&#xff0c;以及如何优化提升检测性能。 &#x1f4a1;&#x1f4a1;&#x1f4a1;加入 DCNv4结合SPPF mAP0.5由原始的0.682提升至…...

(十三)springboot实战——springboot前后端分离方式项目集成spring securtity安全框架

前言 Spring Security 是一款强大且高度可定制的认证和访问控制框架&#xff0c;它是为了保护基于Spring的应用程序提供安全性支持。Spring Security提供了全面的安全服务&#xff0c;主要针对企业级应用程序的需求。其核心组件主要包含&#xff1a;Authentication&#xff08…...

XCTF:3-1[WriteUP]

从题目中获取文件 使用file命令查看文件类型 修改后缀为.rar后进行解压缩 再次使用file命令查询该文件的类型 再次修改后缀为.pcap或者.pcapng 使用wireshark打开&#xff0c;直接搜索flag字样 在多个数据包里发现了flag.rar、flag.txt等文件 尝试使用http导出文件 有一个fl…...

常用ES技巧二

文章目录 一、Object.entries()和Object.fromEntries()1.1、Object.entries()1.2、Object.fromEntries() 二、Symbol类型和Symbol属性三、WeakMap和WeakSet四、Promise.allSettled()五、BigInt六、Array.of和Array.from七、.at和.flat八、总结九、最后 一、Object.entries()和O…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Rating组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Rating组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Rating组件 提供在给定范围内选择评分的组件。 子组件 无。 接口 Rating(opt…...

Python进阶--爬取下载人生格言(基于格言网的Python3爬虫)

目录 一、此处需要安装第三方库: 二、抓包分析及Python代码 1、打开人生格言网&#xff08;人生格言-人生格言大全_格言网&#xff09;进行抓包分析 2、请求模块的代码 3、抓包分析人生格言界面 4、获取目录页中各种类型的人生格言链接 5、获取下一页的链接 5、获取人生…...

FastAdmin

PHP 推荐链接FastAdmin禁用模板布局后台不需要验证权限的接口配置 推荐链接 链接目录 FastAdmin 禁用模板布局 /** 在application/common/controller/Backend.php里面的 _initialize() 方法里面有// 如果有使用模板布局if ($this->layout) {$this->view->engine-…...

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…...

SaperaCamExpert(相机专家)中文使用指南

参考&#xff1a;SaperaCamExpert中文使用指南.PDF 文章目录 软件介绍安装首次打开资源占用率功能主界面布局菜单栏FileViewPre-Processing&#xff1a;预处理 Tools&#xff1a; 快捷键&#xff1a;新建&#xff1b;打开&#xff1b;保存&#xff1b;帮助Device窗体属性树图像…...

ES鉴权设计以及相关探讨

文章目录 1. es的鉴权设计2. es鉴权应用范围3. es鉴权的常用方法3.1 认证体系3.2 x-pack认证3.2.1 开启并配置 X-Pack 的认证与鉴权3.2.2 默认用户和角色3.2.3 创建用户和角色3.2.4 通过用户名和密码访问es 4. 参考文档 鉴权&#xff0c;分别由鉴和权组成 鉴&#xff1a; 表示…...

为什么SpringBoot胖Jar不好

公平地说&#xff0c;我有时会怀念 JavaEE 流行的日子。 当然&#xff0c;当时的情况很复杂&#xff0c;但整个 JavaEE 平台设计合理&#xff0c;符合企业开发的需要。 我可以很轻松地将当时的 JavaEE 应用服务器与现代 Kubernetes 架构进行比较&#xff0c;后者现在也有同样…...

Java学习笔记2024/2/6

练习三&#xff1a;验证码 需求&#xff1a; 定义方法实现随机产生一个5位的验证码 验证码格式&#xff1a; 长度为5 前四位是大写字母或者小写字母 最后一位是数字 package com.angus.comprehensiveExercise; ​ import java.util.Random; ​ public class test3 {publ…...

2024 高级前端面试题之 前端安全模块 「精选篇」

该内容主要整理关于 前端安全模块 的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 前端安全模块精选篇 1. 代码注入XSS如何攻击如何防御cookie 如何防范 XSS 攻击 2. 跨站请求伪造CSRF3. 浏览器同源策略 SOP4. 跨域资源共享 CORS5. 密码…...

SpringBoot Security安全认证框架初始化流程认证流程之源码分析

SpringBoot Security安全认证框架初始化流程&认证流程之源码分析 以RuoYi-Vue前后端分离版本为例分析SpringBoot Security安全认证框架初始化流程&认证流程的源码分析 目录 SpringBoot Security安全认证框架初始化流程&认证流程之源码分析一、SpringBoot Security安…...

2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测

2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效…...

test1

1...

远程主机可能不符合 glibc 和 libstdc++ Vs Code 服务器的先决条件

vscode连接远程主机报错&#xff0c;原因官方已经公布过了&#xff0c;需要远程主机 glibc>2.28&#xff0c;所以Ubuntu18及以下版本没法再远程连接了&#xff0c;其他Linux系统执行ldd --version查看glibc版本自行判断。 解决方案建议&#xff1a; 不要再想升级glibc了 问题…...

备战蓝桥杯---数据结构与STL应用(进阶2)

本文将主要围绕有关map的今典应用展开&#xff1a; 下面我用图进行分析&#xff1a; 下面为AC代码&#xff1a; #include<bits/stdc.h> using namespace std; struct Point {int x,y;bool operator < (const Point & r) const {return x < r.x || ( x r.x &a…...

SpringBoot:多环境配置

多环境配置demo代码&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 方式一、多个properties文件配置 注意&#xff1a;创建properties文件,命名规则&#xff1a;application-&#xff08;环境名称&#xff09; 示例&#xff1a;application-dev.proper…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...