这里鸿蒙的代码使用的是开源鸿蒙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 wifi
int 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_LITE
WIFI_LOGI("Register netsupplier");
WifiNetAgent::GetInstance().OnStaMachineWifiStart();
#endif
/* Initialize Connection Information. */
InitWifiLinkedInfo();
InitLastWifiLinkedInfo();
WifiSettings::GetInstance().SaveLinkedInfo(linkedInfo);
SyncDeviceConfigToWpa();
#ifndef OHOS_ARCH_LITE
ChipCapability::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.c
int 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_SUPPORT
if (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;
}
#endif
LOGI("Start wifi successfully");
return WIFI_HAL_SUCCESS;
}
至此几步完成后,就可以返回 WIFI_HAL_SUCCESS了,在通过RPC回调告诉上层状态,OK,整个鸿蒙 4.0基线的 WiFi 打开流程差不多就梳理完毕了,这里有个疑问,在Android代码我们处理wpa_supplicant,另外还有加载驱动的流程,但这里没有看到,等后续再细看下。