鸿蒙 WiFi 打开流程

这里鸿蒙的代码使用的是开源鸿蒙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,另外还有加载驱动的流程,但这里没有看到,等后续再细看下。

你可能感兴趣的:(OpenHarmony(鸿蒙),harmonyos,华为)