这里鸿蒙的代码使用的是开源鸿蒙HarmonyOS 4.0的代码基线
这里我们是针对手机平台代码分析,首先界面部分代码都在:applications/standard/settings/product/phone
然后我们只关心WiFi相关的,看界面代码applications/standard/settings/product/phone/src/main/ets/pages/wifi.ets
187 build() {
188 Column() {
189 GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
190 Column() {
191 HeadComponent({ headName: $r('app.string.wifiTab'), isActive: true });
192
193 Row() {
194 Text($r('app.string.wifiTab'))
195 .fontSize($r('sys.float.ohos_id_text_size_body1'))
196 .fontColor($r('sys.color.ohos_id_color_text_primary'))
197 .fontWeight(FontWeight.Medium)
198 .textAlign(TextAlign.Start)
199
200 Blank()
201
202 Toggle({ type: ToggleType.Switch, isOn: this.isWiFiEnabled })
203 .width('36vp')
204 .height('20vp')
205 .selectedColor('#007DFF')
206 .onChange((isOn: boolean) => {
207 this.switchWiFiActiveStatus(isOn); ---> 打开 WiFi 触发
208 });
209 }……… ……… ……… ……… ……… ………
386 switchWiFiActiveStatus(isOn: boolean) {
387 // make the ui change quickly
388 this.isWiFiEnabled = isOn;
389 LogUtil.info(MODULE_TAG + 'curr enable status : ' + this.isWiFiEnabled);
390
391 // delay the wifi status change event
392 if (this.switchDebounceFlag) {
393 clearTimeout(this.switchDebounceFlag);
394 }
395
396 if (this.timerId != -1) {
397 clearTimeout(this.timerId);
398 }
399
400 this.switchDebounceFlag = setTimeout(() => {
401 if (this.isWiFiEnabled) {
402 LogUtil.info(MODULE_TAG + 'enable wifi');
403 WifiModel.enableWiFi(); ---> 这里是使能WiFi,跟着流程接着看
404 } else {
405 LogUtil.info(MODULE_TAG + 'disable wifi');
406 WifiModel.disableWifi();
407 }
408 this.switchDebounceFlag = undefined;
409 this.timeLimits();
410 }, 500);
411 }
/applications/standard/settings/product/phone/src/main/ets/model/wifiImpl/WifiModel.ts
280 enableWiFi() {
281 if (wifi.isWifiActive() === true) {
282 LogUtil.info(MODULE_TAG + 'wifi is already active');
283 return;
284 }
285 let ret: boolean = wifi.enableWifi(); ---> 这里的WiFi是:import wifi from '@ohos.wifi';
286 LogUtil.info(MODULE_TAG + 'enable WiFi result is : ' + ret);
287 return ret;
288 }
所以只要找到 @ohos.wifi::enableWifi 方法即可,看这个路径下的配置文件/foundation/communication/wifi/wifi/ 就知道在这里搜下:
// foundation/communication/wifi/wifi/frameworks/native/src/wifi_device_impl.cpp
ErrCode WifiDeviceImpl::EnableWifi()
{std::lock_guard<std::mutex> lock(mutex_);RETURN_IF_FAIL(GetWifiDeviceProxy());return client_->EnableWifi(); ---> 对应的就是相应的代理
}
// /foundation/communication/wifi/wifi/frameworks/native/src/wifi_device_proxy.cpp
ErrCode WifiDeviceProxy::EnableWifi()
{if (mRemoteDied) {WIFI_LOGE("failed to `%{public}s`,remote service is died!", __func__);return WIFI_OPT_FAILED;}MessageOption option;MessageParcel data;MessageParcel reply;if (!data.WriteInterfaceToken(GetDescriptor())) {WIFI_LOGE("Write interface token error: %{public}s", __func__);return WIFI_OPT_FAILED;}data.WriteInt32(0);// 主要就是发送 WIFI_SVR_CMD_ENABLE_WIFI 消息给Stub端,我们看下这个消息 WIFI_SVR_CMD_ENABLE_WIFI = 0x1001,表示open wifiint error = Remote()->SendRequest(static_cast<uint32_t>(DevInterfaceCode::WIFI_SVR_CMD_ENABLE_WIFI), data, reply, option);if (error != ERR_NONE) {WIFI_LOGE("Set Attr(%{public}d) failed,error code is %{public}d",static_cast<int32_t>(DevInterfaceCode::WIFI_SVR_CMD_ENABLE_WIFI), error);return WIFI_OPT_FAILED;}int exception = reply.ReadInt32();if (exception) {return WIFI_OPT_FAILED;}WriteWifiStateHiSysEvent(HISYS_SERVICE_TYPE_STA, WifiOperType::ENABLE);return ErrCode(reply.ReadInt32());
}
// 对应Stub 端 /foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_device_stub.cpp
void WifiDeviceStub::OnEnableWifi(uint32_t code, MessageParcel &data, MessageParcel &reply)
{WIFI_LOGD("run %{public}s code %{public}u, datasize %{public}zu", __func__, code, data.GetRawDataSize());ErrCode ret = EnableWifi(); ---> 找Stub的实现是哪个类即可reply.WriteInt32(0);reply.WriteInt32(ret);return;
}
// 对应这个类:/foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_device_service_impl.cpp
// 这里我们只看和流程相关的,剩下的省内掉
ErrCode WifiDeviceServiceImpl::EnableWifi()
{…………………………do {…………………………IStaService *pService = WifiServiceManager::GetInstance().GetStaServiceInst();if (pService == nullptr) {WIFI_LOGE("Create %{public}s service failed!", WIFI_SERVICE_STA);break;}…………………………errCode = pService->EnableWifi(); // 这里的pService就是 IStaService…………………………
}
那我们就看 IStaService 的 EnableWifi方法,但是发现IStaService 的实现是foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_interface.cpp
ErrCode StaInterface::EnableWifi()
{WIFI_LOGI("Enter StaInterface::EnableWifi.\n");if(pStaService == nullptr) {pStaService = new (std::nothrow) StaService();if (pStaService == nullptr) {WIFI_LOGE("New StaService failed.\n");return WIFI_OPT_FAILED;}if (pStaService->InitStaService(staCallback) != WIFI_OPT_SUCCESS) {WIFI_LOGE("InitStaService failed.\n");delete pStaService;pStaService = nullptr;return WIFI_OPT_FAILED;}}if (pStaService->EnableWifi() != WIFI_OPT_SUCCESS) { ---> 我们还是只关心打开相关的流程WIFI_LOGE("EnableWifi failed.\n");DisableWifi();return WIFI_OPT_FAILED;}return WIFI_OPT_SUCCESS;
}
// 接着看 StaService 里面的EnableWifi 方法:foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_service.cpp
ErrCode StaService::EnableWifi() const
{WIFI_LOGI("Enter StaService::EnableWifi.\n");CHECK_NULL_AND_RETURN(pStaStateMachine, WIFI_OPT_FAILED);pStaStateMachine->SendMessage(WIFI_SVR_CMD_STA_ENABLE_WIFI, STA_CONNECT_MODE); ---> 状态机里面处理return WIFI_OPT_SUCCESS;
}
看状态机里面如何处理这个 WIFI_SVR_CMD_STA_ENABLE_WIFI,对应的定义
#define WIFI_SVR_CMD_STA_ENABLE_WIFI 0x2001
// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_state_machine.cpp
bool StaStateMachine::InitState::ExecuteStateMsg(InternalMessage *msg)
{if (msg == nullptr) {return false;}WIFI_LOGI("InitState-msgCode=%{public}d is received.\n", msg->GetMessageName());bool ret = NOT_EXECUTED;switch (msg->GetMessageName()) {case WIFI_SVR_CMD_STA_ENABLE_WIFI: {ret = EXECUTED;pStaStateMachine->operationalMode = msg->GetParam1();pStaStateMachine->StartWifiProcess();break;}case WIFI_SVR_CMD_STA_OPERATIONAL_MODE:break;default:WIFI_LOGI("InitState-msgCode=%d not handled.\n", msg->GetMessageName());break;}return ret;
}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(); ---> 启动WiFi }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);}
}
看下 WifiStaHalInterface::GetInstance().StartWifi(); —> 启动WiFi 的流程
// foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_sta_hal_interface.cpp
WifiErrorNo WifiStaHalInterface::StartWifi(void)
{CHECK_NULL_AND_RETURN(mIdlClient, WIFI_IDL_OPT_FAILED);return mIdlClient->StartWifi(); // 而 mIdlClient = new (std::nothrow) WifiIdlClient;
}
// 所以看/foundation/communication/wifi/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_idl_client.cpp
WifiErrorNo WifiIdlClient::StartWifi(void)
{CHECK_CLIENT_NOT_NULL;return Start();
}
这里 wifi_idl_client 实现了与 Wifi HAL 进行 RPC 通信的客户端,那服务端必然就是 Wifi HAL,后续我们再去记录具体的,这里我们只关心流程,就直接贴上远端(服务端)的代码位置
foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_crpc_server.c
// wifi_hal_crpc_server.c 可以看到代码位置已经是wifi_hal了,就验证了我们上面的那句话ret += PushRpcFunc("Start", RpcStart); ---> Start 对应的方法是 RpcStart// foundation/communication/wifi/wifi/services/wifi_standard/wifi_hal/wifi_hal_crpc_sta.cint RpcStart(RpcServer *server, Context *context)
{if (server == NULL || context == NULL) {return HAL_FAILURE;}WifiErrorNo err = Start(); ---> 看这个WriteBegin(context, 0);WriteInt(context, err);WriteEnd(context);return HAL_SUCCESS;
}
// 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) { ---》 启动 supplicant,主要是去加载对应的库文件,这个很熟悉了LOGE("wpa_supplicant start failed!");return WIFI_HAL_OPEN_SUPPLICANT_FAILED;}LOGI("wpa_supplicant start successfully!");if (AddWpaIface(0) != WIFI_HAL_SUCCESS) { ---》 添加wlan0 接口LOGE("Failed to add wpa interface!");StopWpaAndWpaHal(0);return WIFI_HAL_CONN_SUPPLICANT_FAILED;}if (ConnectSupplicant() != WIFI_HAL_SUCCESS) { ---》看代码其实就是得到操作wpa的方法,一一对应起来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了,在通过RPC回调告诉上层状态,OK,整个鸿蒙 4.0基线的 WiFi 打开流程差不多就梳理完毕了,这里有个疑问,在Android代码我们处理wpa_supplicant,另外还有加载驱动的流程,但这里没有看到,等后续再细看下。