作者:李威
簡介
Wi-Fi是WLAN具體采用的技術,也是目前WLAN的主流技術。Wi-Fi采用的技術是IEEE80211系列協(xié)議,IEEE (Institute of Electrical and Electronics Engineers)是美國電氣和電子工程師協(xié)會的簡稱。
STA模式:Station,類似于無線終端,sta本身并不接受無線的接入,它可以連接到AP(AccessPoint),一般無線網(wǎng)卡即工作在該模式,這是Wifi最基本的工作模式。
Wifi子系統(tǒng)架構
Wifi架構解析
Wi-Fi App:
主要是開發(fā)者自行開發(fā)Wi-Fi相關功能的應用。通過調用Wifi SDK對外提供的API實現(xiàn)對設備Wi-Fi的控制及其功能實現(xiàn)。這一層平臺將會提供相關的API調用示例,以供參考。
Wi-Fi Native JS:
JS層使用NAPI機制開發(fā),連接APP層與Framework層,將wifi功能封裝成JS接口提供給應用調用,并同時支持Promise和Callback異步回調。
Wi-Fi Framework:
Wi-Fi核心功能實現(xiàn)。直接為上層應用提供服務。根據(jù)其工作模式的不同分為四大業(yè)務服務模塊,分別是STA服務、AP服務、P2P服務、Aware服務,同時DHCP功能。
Wi-Fi Hal:
為FrameWork層操作Wi-Fi硬件提供統(tǒng)一的接口服務,實現(xiàn)應用框架與硬件操作的分離。主要包括Hal適配器及擴展Hal模塊及Wi-Fi硬件廠家提供的二進制庫模塊。
WPA Supplicant:
包含wpa_supplicant和hosapd兩個子模塊,wpa_supplicant和hostapd實現(xiàn)了定義好的驅動API,對外提供控制接口,框架就能通過其控制接口來實現(xiàn)Wifi的各種操作。wpa_supplicant支持STA及P2P模式,hostapd則支持AP模式。
HDF:
HDF 驅動框架主要由驅動基礎框架、驅動程序、驅動配置文件和驅動接口這四個部分組成,實現(xiàn)WIfi驅動功能,加載驅動,驅動接口部署等。
Wi-Fi Kernel:
包含Wi-Fi 驅動,包括了對設備的一些基本的讀寫操作由Wi-Fi驅動移植人員編譯進內核。
代碼結構
/foundation/communication/wifi
├── figures # 圖片資源目錄
├── interfaces # 接口適配目錄
│ ├── innerkits # 內部接口適配目錄
│ └── kits # WLAN組件接口的適配代碼存放目錄
├── services # service適配目錄
│ └── wifi_standard # service實現(xiàn)目錄
├── tests # 測試代碼目錄
│ └── wifi_standard # service實現(xiàn)模塊測試代碼
└── utils # 實用函數(shù)目錄
├── inc # 實用函數(shù)頭文件目錄
└── src # 實用函數(shù)實現(xiàn)目錄
關鍵模塊實現(xiàn)
IPC通信
Native JS和Wifi框架通過IPC(Inter-Process Communication)進行通信,實現(xiàn)接口調用及事件傳遞。IPC通信采用客戶端-服務器(Client-Server)模型,服務請求方(Client)可獲取提供服務提供方(Server)的代理 (Proxy),并通過此代理讀寫數(shù)據(jù)來實現(xiàn)進程間的數(shù)據(jù)通信。
在鴻蒙系統(tǒng)中,首先服務端注冊系統(tǒng)能力(System Ability)到系統(tǒng)能力管理者(System Ability Manager,縮寫SAMgr),SAMgr負責管理這些SA并向客戶端提供相關的接口??蛻舳艘湍硞€具體的SA通信,必須先從SAMgr中獲取該SA的代理,然后使用代理和服務端通信,Proxy表示服務請求方,Stub表示服務提供方。
Wifi系統(tǒng)對不同模式各實現(xiàn)了一套Proxy-Stub類,STA模式分別是WifiDeviceProxy和WifiDeviceStub,WifiScanProxy和WifiScanStub,對掃描和其他STA流程進行了分離。
由圖所示,首先WifiDeviceImpl是Native JS層WifiDevice的實現(xiàn)類,是服務請求方,作為IPC服務客戶端,WifiDeviceProxy作為代理類,通過它來向服務方發(fā)起請求;WifiDeviceStub作為服務方接收請求并處理;WifiDeviceServiceImpl繼承WifiDeviceStub類和SystemAbility類,是IPC通信服務方的具體實現(xiàn)。
以WifiDeviceProxy和WifiDeviceStub為例,分別從代理方和服務方說明實現(xiàn)過程。
WiFi Native JS作為服務請求方發(fā)起流程時,WifiDeviceImpl初始化通過Init函數(shù)構造代理WifiDeviceProxy,步驟如下:
首先,獲取SAMgr。
然后,通過SAMgr及相應的ability id獲取到對應SA的代理IRemoteObject。
最后,使用IRemoteObject構造WifiDeviceProxy。
目錄:foundation/communication/wifi/interfaces/innerkits/native_cpp/wifi_standard/src/wifi_device_impl.cpp
```c++
bool WifiDeviceImpl::Init()
{
//獲取SAMgr
sptr<ISystemAbilityManager> sa_mgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sa_mgr == nullptr) {
WIFI_LOGE("failed to get SystemAbilityManager");
return false;
}
//通過SAMgr及相應的ability id獲取到對應SA的代理IRemoteObject
sptr<IRemoteObject> object = samgr->GetSystemAbility(systemAbilityId);
if (object == nullptr) {
WIFI_LOGE("failed to get DEVICESERVICE");
return false;
}
//使用IRemoteObject構造WifiDeviceProxy
client = ifacecast<IWifiDevice>(object);
if (client == nullptr) {
client_ = new (std::nothrow) WifiDeviceProxy(object); //構造代理
}
if (client_ == nullptr) {
WIFI_LOGE("wifi device init failed. %{public}d", systemAbilityId_);
return false;
}
return true;
}
我們以打開WiFi為例看看其調用過程,客戶端發(fā)起請求后,接口層提供WifiDeviceProxy作為代理發(fā)送打開WiFi請求:
**目錄:foundation/communication/wifi/interfaces/innerkits/native_cpp/wifi_standard/src/wifi_device_proxy.cpp**
```c++
ErrCode WifiDeviceProxy::EnableWifi()
{
if (mRemoteDied) {
WIFI_LOGD("failed to `%{public}s`,remote service is died!", __func__);
return WIFI_OPT_FAILED;
}
MessageOption option;
MessageParcel data;
MessageParcel reply;
data.WriteInt32(0);
int error = Remote()->SendRequest(WIFI_SVR_CMD_ENABLE_WIFI, data, reply, option); //向服務方發(fā)送WIFI_SVR_CMD_ENABLE_WIFI請求
if (error != ERR_NONE) {
WIFI_LOGE("Set Attr(%{public}d) failed,error code is %{public}d", WIFI_SVR_CMD_ENABLE_WIFI, error);
return WIFI_OPT_FAILED;
}
int exception = reply.ReadInt32();
if (exception) {
return WIFI_OPT_FAILED;
}
return ErrCode(reply.ReadInt32());
}
WifiDeviceProxy繼承自IRemoteProxy,封裝WiFi Station模式相關業(yè)務函數(shù),調用SendRequest將請求發(fā)到服務端Stub。
WiFi框架提供服務方WifiDeviceStub,繼承IRemoteStub,實現(xiàn)了IWifiDevice接口類中未實現(xiàn)的方法,并重寫了OnRemoteRequest方法。Proxy請求方發(fā)來的請求就在OnRemoteRequest中處理。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_device_stub.cpp
```c++
int WifiDeviceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
int exception = data.ReadInt32();
if (exception) {
return WIFI_OPT_FAILED;
}
HandleFuncMap::iterator iter = handleFuncMap.find(code);
if (iter == handleFuncMap.end()) {
WIFI_LOGI("not find function to deal, code %{public}u", code);
reply.WriteInt32(0);
reply.WriteInt32(WIFI_OPT_NOT_SUPPORTED);
} else {
(this->*(iter->second))(code, data, reply);
}
return 0;
}
WifiDeviceStub對proxy請求事件和相應處理函數(shù)進行了映射。
```c++
void WifiDeviceStub::InitHandleMap()
{
handleFuncMap[WIFI_SVR_CMD_ENABLE_WIFI] = &WifiDeviceStub::OnEnableWifi; //打開wifi
handleFuncMap[WIFI_SVR_CMD_DISABLE_WIFI] = &WifiDeviceStub::OnDisableWifi;
......
return;
}
根據(jù)映射關系調用其OnEnableWifi方法:
```c++
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();
reply.WriteInt32(0);
reply.WriteInt32(ret);
return;
}
這里調用EnableWifi(),其具體實現(xiàn)在子類WifiDeviceServiceImpl。
WifiDeviceServiceImpl作為IPC通信服務方的具體實現(xiàn),如以下代碼所示,WifiDeviceServiceImpl通過MakeAndRegisterAbility將WifiDeviceServiceImpl實例注冊到SAMgr。接下來,服務請求方就可以通過從SAMgr獲取代理來和服務提供方通信。
```c++
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(WifiDeviceServiceImpl::GetInstance().GetRefPtr());
sptr<WifiDeviceServiceImpl> WifiDeviceServiceImpl::GetInstance()
{
if (g_instance == nullptr) {
std::lock_guard<std::mutex> autoLock(g_instanceLock);
if (g_instance == nullptr) {
auto service = new (std::nothrow) WifiDeviceServiceImpl;
g_instance = service;
}
}
return g_instance;
}
WifiDeviceServiceImpl::WifiDeviceServiceImpl()
: SystemAbility(WIFI_DEVICE_ABILITY_ID, true), mPublishFlag(false), mState(ServiceRunningState::STATE_NOT_START)
{}
狀態(tài)機管理
Wifi框架維護了四個狀態(tài)機,分別是sta statemachine、scan statemachine、p2p statemachine和ap statemachine。Wifi各個模式工作流程中會涉及到各個不同的階段,需要對不同階段的狀態(tài)進行管理。對于Native JS通過代理發(fā)送到Wifi框架的請求以及HAL回送的WPA Supplicant的響應,需要在相應模式的相應狀態(tài)下做合適的處理。
本章僅介紹Wifi基本模式STA和Scan的狀態(tài)機。
STA狀態(tài)機維護了wifi打開、關閉、連接、獲取IP及漫游的狀態(tài)及切換。Wifi打開時,會啟動staService,構造sta statemachine并初始化。如STA狀態(tài)機樹狀圖所示,sta statemachine在初始化時,會創(chuàng)建狀態(tài)樹,創(chuàng)建子狀態(tài)必須保證相應的父狀態(tài)被創(chuàng)建。當遷移到子狀態(tài),子狀態(tài)激活,也就是執(zhí)行GoInState后,其父節(jié)點會同時處于激活狀態(tài),不會調用GoOutState,子節(jié)點共同需要處理的事件或者不關心的事件由父狀態(tài)處理,子狀態(tài)只負責處理自己感興趣的消息。
比如wifi打開時,狀態(tài)機從InitState遷移到目標狀態(tài)SeparatedState,這時處于激活狀態(tài)的有WpaStartedState及LinkState。
當wifi關閉時,WpaStartedState處理WIFI_SVR_CMD_STA_DISABLE_WIFI事件,關閉wifi,回到InitState狀態(tài)。
當用戶連接網(wǎng)絡時,LinkState處理CMD_START_CONNECT_SELECTED_NETWORK事件進行連接網(wǎng)絡的動作,收到WIFI_SVR_CMD_STA_NETWORK_CONNECTION_EVENT后,狀態(tài)遷移到GetIpState狀態(tài),同時ApLinkedState狀態(tài)處于激活。在GetIpState狀態(tài),如果IP地址分配成功,則進入LinkedState。如果分配失敗,則回到SeparatedState。
不管是在GetIpState還是在LinkedState,只要收到斷開網(wǎng)絡請求WIFI_SVR_CMD_STA_DISCONNECT,都由ApLinkedState處理,進入SeparatedState。
Scan狀態(tài)機維護了wifi普通掃描,pno掃描(硬件掃描和軟件掃描)的狀態(tài)及切換過程。
這里對PNO掃描稍加說明,PNO掃描即Preferred Network Offload,用于系統(tǒng)在休眠的時候連接WiFi,當手機休眠時,存在已經(jīng)保存的網(wǎng)絡并且沒有連接時,進行PNO掃描,只掃描已保存的網(wǎng)絡。PNO模式能讓設備在熄屏時通過搜索最近連接過的Wifi網(wǎng)絡,從而優(yōu)先連接至Wifi網(wǎng)絡,達到延長續(xù)航時間并且減少手機數(shù)據(jù)流量消耗的目的。
Wifi打開后,啟動scanService同時構造scan statemachine并初始化,與sta statemachine相同,scan statemachine按照Scan狀態(tài)機樹狀圖所示創(chuàng)建狀態(tài)機各個狀態(tài)。
scan statemachine初始化時設置狀態(tài)為InitState,隨后發(fā)送CMD_SCAN_PREPARE給InitState,進入HardwareReady狀態(tài)。
處于HardwareReady狀態(tài)時Native JS調用scan接口進行掃描,HardwareReady會收到CMD_START_COMMON_SCAN消息進入CommonScanning狀態(tài),掃描成功、失敗或者超時后進入CommonScanUnworked狀態(tài),如果這時候再次發(fā)起掃描則會回到CommonScanning狀態(tài)。
處于HardwareReady狀態(tài)時發(fā)起PNO掃描時,首先判斷系統(tǒng)是否支持硬件PNO掃描,如果支持,則進入PnoScanHardware狀態(tài),向底層下發(fā)PNO掃描命令。
在PnoScanHardware狀態(tài),如果收到PNO掃描結果通知,并且NeedCommonScanAfterPno為true,則進入CommonScanAfterPno狀態(tài),等收到CMD_START_COMMON_SCAN進入CommonScanning,或者收到普通掃描命令,進入HardwareReady狀態(tài)準備進行普通掃描,否則一直處于PNO硬件掃描狀態(tài)。
當發(fā)起PNO掃描后,如果系統(tǒng)不支持硬件PNO掃描,則進入PnoScanSoftware狀態(tài),啟動一次軟件PNO掃描,進入PnoSwScanning狀態(tài),掃描成功或者失敗或者超時后進入PnoSwScanFree狀態(tài)。
在PnoSwScanFree狀態(tài),收到CMD_START_COMMON_SCAN命令,則回到HardwareReady狀態(tài)準備進行一次普通掃描;如果收到PNO掃描命令則回到PnoSwScanning狀態(tài)。
STA業(yè)務代碼流程
前面講過,Native Js發(fā)起調用,經(jīng)過IPC通信,調用到WifiDeviceServiceImpl作為服務端的實現(xiàn)。
Wifi打開流程
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_device_service_impl.cpp
```c++
ErrCode WifiDeviceServiceImpl::EnableWifi()
{
...
errCode = WIFI_OPT_FAILED;
do {
if (WifiServiceManager::GetInstance().CheckAndEnforceService(WIFI_SERVICE_STA) < 0) {//加載STA服務
break;
}
IStaService *pService = WifiServiceManager::GetInstance().GetStaServiceInst(); //構建StaService
if (pService == nullptr) {
WIFI_LOGE("Create %{public}s service failed!", WIFI_SERVICE_STA);
break;
}
errCode = pService->RegisterStaServiceCallback(WifiManager::GetInstance().GetStaCallback()); //注冊回調函數(shù)
if (errCode != WIFI_OPT_SUCCESS) {
WIFI_LOGE("Register sta service callback failed!");
break;
}
errCode = pService->EnableWifi(); //打開wifi
if (errCode != WIFI_OPT_SUCCESS) {
WIFI_LOGE("service enable sta failed, ret %{public}d!", static_cast<int>(errCode));
break;
}
} while (false);
...
return WIFI_OPT_SUCCESS;
}
這里主要做了四件事情:
1. 加載STA服務,在WifiServiceManager中根據(jù)服務名稱WIFI_SERVICE_STA,調用LoadStaService方法加載STA服務;
2. 構建StaService,獲取接口IStaService實例;
3. 注冊回調函數(shù);
4. 調用StaService打開Wifi。
StaService是Wifi框架層Station服務的主要實現(xiàn),通過創(chuàng)建StaStateMachine和StaMonitor對Wifi Station命令和事件進行處理。
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_service.cpp**
StaService首先在調用之前,首先會初始化:
```c++
ErrCode StaService::InitStaService(const StaServiceCallback &callbacks)
{
WIFI_LOGI("Enter StaService::InitStaService.
");
pStaStateMachine = new (std::nothrow) StaStateMachine(); //構造StaStateMachine狀態(tài)機
...
RegisterStaServiceCallback(callbacks); //注冊事件回調函數(shù)
pStaMonitor = new (std::nothrow) StaMonitor(); //構造StaMonitor并初始化
...
pStaMonitor->SetStateMachine(pStaStateMachine);
pStaAutoConnectService = new (std::nothrow) StaAutoConnectService(pStaStateMachine); //構造自動連接服務
...
WIFI_LOGI("Init staservice successfully.
");
return WIFI_OPT_SUCCESS;
}
初始化主要會做四件事:
1.構造StaStateMachine狀態(tài)機
2.注冊回調函數(shù)
3.構造StaMonitor
4.構造自動連接服務
這些準備工作做完后,就是真正執(zhí)行EnableWifi的流程。
```c++
ErrCode StaService::EnableWifi() const
{
WIFI_LOGI("Enter StaService::EnableWifi.
");
pStaStateMachine->SendMessage(WIFI_SVR_CMD_STA_ENABLE_WIFI, STA_CONNECT_MODE); //向StaStateMachine發(fā)送WIFI_SVR_CMD_STA_ENABLE_WIFI消息
return WIFI_OPT_SUCCESS;
}
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_state_machine.cpp**
StaStateMachine在初始化時設置初始狀態(tài)為InitState ,”SetFirstState(pInitState)“,故接收到WIFI_SVR_CMD_STA_ENABLE_WIFI在InitState狀態(tài)中處理:
```c++
bool StaStateMachine::InitState::ExecuteStateMsg(InternalMessage *msg)
{
if (msg == nullptr) {
return false;
}
bool ret = NOT_EXECUTED;
switch (msg->GetMessageName()) {
case WIFI_SVR_CMD_STA_ENABLE_WIFI: { //StastateMachine接收到WIFI_SVR_CMD_STA_ENABLE_WIFI消息
ret = EXECUTED;
pStaStateMachine->operationalMode = msg->GetParam1();
pStaStateMachine->StartWifiProcess(); //調用StartWifiProcess()方法
break;
}
case WIFI_SVR_CMD_STA_OPERATIONAL_MODE:
break;
default:
LOGI("InitState-msgCode=%d not handled.
", msg->GetMessageName());
break;
}
return ret;
}
```c++
void StaStateMachine::StartWifiProcess()
{
WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::ENABLING));
staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_OPENING);
int res = WifiStaHalInterface::GetInstance().StartWifi(); //調用WifiStaHalInterface的StartWifi()
//下面是對返回結果的處理
...
}
WifiStaHalInterface是框架調用Wifi Hal的接口。
框架與Wifi Hal的通信主要是借助IDL Client組件,采用RPC服務實現(xiàn)其交互。
無論是框架調用Wifi Hal還是Wifi Hal回調消息到框架,都要經(jīng)過IDL Clinet,從架構圖來看,它屬于Wifi框架的一部分,我們先來看看它。
IDL客戶端初始化:
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_base_hal_interface.cpp**
```c++
bool WifiBaseHalInterface::InitIdlClient(void)
{
if (mIdlClient == nullptr) {
mIdlClient = new (std::nothrow) WifiIdlClient;
}
if (mIdlClient == nullptr) {
LOGE("Failed to create idl client");
return false;
}
if (mIdlClient->InitClient() != 0) {
LOGE("Failed to init idl client");
return false;
}
return true;
}
IDL客戶端初始化主要做了兩件事:
1.構造WifiIdlClient實例
2.初始化RPC通信客戶端
```c++
int WifiIdlClient::InitClient(void)
{
const std::string idlSockPath = "/data/misc/wifi/unix_sock.sock";
pRpcClient = CreateRpcClient(idlSockPath.c_str());
if (pRpcClient == nullptr) {
LOGE("init rpc client failed!");
return -1;
}
return 0;
}
有了WifiIdlClient實例,調用其StartWifi()。
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_sta_hal_interface.cpp**
```c++
WifiErrorNo WifiStaHalInterface::StartWifi(void)
{
return mIdlClient->StartWifi();
}
通過wifi_idl_client向wifi hal發(fā)起RPC調用“Start”。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/wifi_idl_client.cpp
```c++
WifiErrorNo WifiIdlClient::StartWifi(void)
{
CHECK_CLIENT_NOT_NULL;
return Start();
}
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/idl_client/idl_interface/i_wifi.c**
```c
WifiErrorNo Start(void)
{
RpcClient *client = GetStaRpcClient();
LockRpcClient(client);
Context *context = client->context;
WriteBegin(context, 0);
WriteFunc(context, "Start");
WriteEnd(context);
if (RpcClientCall(client, "Start") != WIFI_IDL_OPT_OK) {
return WIFI_IDL_OPT_FAILED;
}
int result = WIFI_IDL_OPT_FAILED;
ReadInt(context, &result);
ReadClientEnd(client);
UnlockRpcClient(client);
return result;
}
這里主要操作是獲取RPC調用客戶端,然后通過RemoteCall(client)方法發(fā)起遠程調用。
Wifi Hal作為RPC服務端,啟動后調用InitRpcFunc初始化RPC函數(shù),然后CreateRpcServer創(chuàng)建RPC服務,最后調用RunRpcLoop循環(huán)讀取遠程調用信息,處理客戶端請求。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/main.c
int main(void)
{
char rpcSockPath[] = "/data/misc/wifi/unix_sock.sock";
if (access(rpcSockPath, 0) == 0) {
unlink(rpcSockPath);
}
if (InitRpcFunc() < 0) { //
LOGE("Init Rpc Function failed!");
return -1;
}
RpcServer *server = CreateRpcServer(rpcSockPath); //framework中server.c
if (server == NULL) {
LOGE("Create RPC Server by %{public}s failed!", rpcSockPath);
return -1;
}
SetRpcServerInited(server);
setvbuf(stdout, NULL, _IOLBF, 0);
signal(SIGINT, SignalExit);
signal(SIGTERM, SignalExit);
signal(SIGPIPE, SIG_IGN);
RunRpcLoop(server);
/* stop wpa_supplicant, hostapd, and other resources */
ForceStop();
StopSoftAp();
P2pForceStop();
ReleaseWifiHalVendorInterface();
/* clear RPC Server */
SetRpcServerInited(NULL);
ReleaseRpcServer(server);
ReleaseRpcFunc();
LOGI("hal service exists!");
return 0;
}
InitRpcFunc中Map了“Start”消息的處理函數(shù),PushRpcFunc("Start", RpcStart)。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/wifi_hal_crpc_server.c
static int InitRpcFuncMapSta(void)
{
int ret = 0;
ret += PushRpcFunc("Start", RpcStart);
ret += PushRpcFunc("Stop", RpcStop);
......
return ret;
}
根據(jù)配對關系調用到RpcStart,
目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/wifi_hal_crpc_sta.c
int RpcStart(RpcServer *server, Context *context)
{
if (server == NULL || context == NULL) {
return -1;
}
WifiErrorNo err = Start(); //調用Start方法
WriteBegin(context, 0);
WriteInt(context, err);
WriteEnd(context);
return 0;
}
調用Start()實際操作實現(xiàn)在wifi_hal_sta_interface的Start函數(shù),調用完成。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c
WifiErrorNo Start(void)
{
LOGD("Ready to start wifi");
if (StartSupplicant() != WIFI_HAL_SUCCESS) { //start supplicant
LOGE("wpa_supplicant start failed!");
return WIFI_HAL_OPEN_SUPPLICANT_FAILED;
}
LOGD("wpa_supplicant start successfully!");
if (AddWpaIface(0) != WIFI_HAL_SUCCESS) { //Add a new interface wlan0
LOGE("Failed to add wpa interface!");
StopWpaAndWpaHal(0);
return WIFI_HAL_CONN_SUPPLICANT_FAILED;
}
if (ConnectSupplicant() != WIFI_HAL_SUCCESS) { //構造并初始化WifiWpaStaInterface
LOGE("SupplicantHal connect wpa_supplicant failed!");
StopWpaAndWpaHal(0);
return WIFI_HAL_CONN_SUPPLICANT_FAILED;
}
LOGD("SupplicantHal connect wpa_supplicant successfully!");
LOGD("Start wifi successfully");
return WIFI_HAL_SUCCESS;
}
主要做了三步操作:
- start supplicant
命令:wpa_supplicant -iglan0 -g/data/misc/wifi/sockets
```c++
const char *wpaConf = "/data/misc/wifi/wpa_supplicant/wpa_supplicant.conf";
2. Add a new interface wlan0
命令:interface_add wlan0 /data/misc/wifi/wpa_supplicant/wpa_supplicant.conf
```c++
pWpaInterface->wpaCliAddIface(pWpaInterface, &argv)
-
構造并初始化WifiWpaStaInterface,封裝了wpa_supplicant關于STA的操作命令。
```c++
WifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);
以上三步成功后,RPC調用返回WIFI_HAL_SUCCESS,日志會打印"Start wifi successfully"。
StaStateMachine在EnableWifi成功后,設置wifistate為ENABLED并執(zhí)行OnStaOpenRes回調:
```c++
WifiSettings::GetInstance().SetWifiState(static_cast<int>(WifiState::ENABLED));
staCallback.OnStaOpenRes(OperateResState::OPEN_WIFI_SUCCEED);
回調在WifiManager中處理,廣播wifi狀態(tài)改變消息,構造ScanService并初始化,初始化過程做了這幾件事:
1. 構造ScanStateMachine并初始化,調用EnrollScanStatusListener綁定Scan狀態(tài)上報事件的處理函數(shù)。
2. 構造ScanMonitor并初始化,在初始化函數(shù)中調用RegisterSupplicantEventCallback,注冊supplicant事件回調。
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_service.cpp**
```c++
bool ScanService::InitScanService(const IScanSerivceCallbacks &scanSerivceCallbacks)
{
WIFI_LOGI("Enter ScanService::InitScanService.
");
mScanSerivceCallbacks = scanSerivceCallbacks;
//構造ScanStateMachine
pScanStateMachine = new (std::nothrow) ScanStateMachine();
if (pScanStateMachine == nullptr) {
WIFI_LOGE("Alloc pScanStateMachine failed.
");
return false;
}
//初始化ScanStateMachine
if (!pScanStateMachine->InitScanStateMachine()) {
WIFI_LOGE("InitScanStateMachine failed.
");
return false;
}
//綁定Scan狀態(tài)上報事件的處理函數(shù)
if (!pScanStateMachine->EnrollScanStatusListener(
std::bind(&ScanService::HandleScanStatusReport, this, std::placeholders::_1))) {
WIFI_LOGE("ScanStateMachine_->EnrollScanStatusListener failed.
");
return false;
}
//構造ScanMonitor
pScanMonitor = new (std::nothrow) ScanMonitor();
if (pScanMonitor == nullptr) {
WIFI_LOGE("Alloc pScanMonitor failed.
");
return false;
}
//初始化ScanMonitor
if (!pScanMonitor->InitScanMonitor()) {
WIFI_LOGE("InitScanMonitor failed.
");
return false;
}
//獲取支持頻段
if ((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.
");
}
pScanMonitor->SetScanStateMachine(pScanStateMachine);
//向ScanStateMachine發(fā)送CMD_SCAN_PREPARE
pScanStateMachine->SendMessage(static_cast<int>(CMD_SCAN_PREPARE));
GetScanControlInfo();
return true;
}
ScanStateMachine初始化狀態(tài)為InitState,然后接收到CMD_SCAN_PREPARE消息,調用LoadDriver();
```c++
bool ScanStateMachine::InitState::ExecuteStateMsg(InternalMessage *msg)
{
......
switch (msg->GetMessageName()) {
case CMD_SCAN_PREPARE:
LoadDriver();
return true;
case CMD_SCAN_FINISH:
UnLoadDriver();
return true;
......
default:
return false;
}
}
```c++
void ScanStateMachine::InitState::LoadDriver()
{
WIFI_LOGI("Enter ScanStateMachine::LoadDriver.
");
pScanStateMachine->SwitchState(pScanStateMachine->hardwareReadyState);
pScanStateMachine->ReportStatusChange(SCAN_STARTED_STATUS);
WIFI_LOGI("Start Scan Service Success.
");
}
LoadDriver()做了兩件事情:
- ScanStateMAchine切換狀態(tài)為為HardwareReadyState
- 上報SCAN_STARTED_STATUS狀態(tài)
然后就可以發(fā)起掃描的流程了。
掃描流程
應用調用Native JS的Scan接口,會通過獲取WifiScan實例,調用C++接口,發(fā)起IPC通信,通過WifiScanProxy向服務框架發(fā)送WIFI_SVR_CMD_FULL_SCAN請求。WifiScanStub作為服務端接收到請求,WifiScanServiceImpl作為服務端的主要實現(xiàn)。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan_service_impl.cpp
```c++
ErrCode WifiScanServiceImpl::Scan()
{
WIFI_LOGI("Scan");
.....
//判斷ScanService是否啟動
if (!IsScanServiceRunning()) {
return WIFI_OPT_SCAN_NOT_OPENED;
}
//獲取IScanService實例
IScanService *pService = WifiServiceManager::GetInstance().GetScanServiceInst();
if (pService == nullptr) {
return WIFI_OPT_SCAN_NOT_OPENED;
}
return pService->Scan(true);
}
構造ScanService,通過IScanService接口調用其Scan方法:
```c++
ErrCode ScanService::Scan(bool externFlag)
{
WIFI_LOGI("Enter ScanService::Scan.
");
if (!scanStartedFlag) {
WIFI_LOGE("Scan service has not started.
");
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.
");
}
//構造ScanConfig
scanConfig.scanBand = SCAN_BAND_BOTH_WITH_DFS;
scanConfig.fullScanFlag = true;
scanConfig.externFlag = externFlag;
scanConfig.scanStyle = SCAN_TYPE_HIGH_ACCURACY;
if (!SingleScan(scanConfig)) {
WIFI_LOGE("SingleScan failed.
");
return WIFI_OPT_FAILED;
}
return WIFI_OPT_SUCCESS;
}
這里首先構造scanConfig,然后調用SingleScan向ScanStateMachine發(fā)送CMD_START_COMMON_SCAN命令并攜帶scanConfig,
```c++
//保存scanConfig
int requestIndex = StoreRequestScanConfig(scanConfig, interConfig);
//生成Message
InternalMessage *interMessage = pScanStateMachine->CreateMessage(static_cast<int>(CMD_START_COMMON_SCAN), requestIndex);
//發(fā)送消息
pScanStateMachine->SendMessage(interMessage);
ScanService初始化完成后,ScanStateMachine處于HardwareReady是可以發(fā)起掃描的激活狀態(tài),
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_scan/scan_state_machine.cpp**
```c++
bool ScanStateMachine::HardwareReady::ExecuteStateMsg(InternalMessage *msg)
{
WIFI_LOGI("ScanStateMachine::HardwareReady::ExecuteStateMsg.
");
if (msg == nullptr) {
WIFI_LOGE("msg is null.
");
return true;
}
switch (msg->GetMessageName()) {
//處理CMD_START_COMMON_SCAN消息
case CMD_START_COMMON_SCAN:
pScanStateMachine->CommonScanRequestProcess(msg);
return true;
case CMD_START_PNO_SCAN:
pScanStateMachine->PnoScanRequestProcess(msg);
return true;
default:
return false;
}
}
接收CMD_START_COMMON_SCAN并處理,進行獲取掃描參數(shù)的操作,并校驗Scan類型是否合法,之后轉換掃描參數(shù),通過RPC調用HAL的scan操作,
```c++
WIFI_LOGI("Begin call Scan.
");
WifiErrorNo ret = WifiStaHalInterface::GetInstance().Scan(scanParam);
if ((ret != WIFI_IDL_OPT_OK) && (ret != WIFI_IDL_OPT_SCAN_BUSY)) {
WIFI_LOGE("WifiStaHalInterface::GetInstance().scan failed.");
return false;
}
WIFI_LOGI("End call Scan.
");
HAL得到scan配置參數(shù)后,通過wpaCliCmdScan向supplicant發(fā)送SCAN命令,
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c**
```c++
WifiErrorNo StartScan(const ScanSettings *settings)
{
LOGD("Ready to start scan with param.");
WifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);
if (pStaIfc == NULL) {
return WIFI_HAL_SUPPLICANT_NOT_INIT;
}
int ret = pStaIfc->wpaCliCmdScan(pStaIfc, settings); //向supplicant發(fā)送SCAN命令
if (ret < 0) {
LOGE("StartScan failed! ret=%{public}d", ret);
return WIFI_HAL_FAILED;
}
if (ret == WIFI_HAL_SCAN_BUSY) {
LOGD("StartScan return scan busy");
return WIFI_HAL_SCAN_BUSY;
}
LOGD("StartScan successfully!");
return WIFI_HAL_SUCCESS;
}
掃描成功,HAL返回WIFI_HAL_SUCCESS。
調用成功StaStateMachine切換狀態(tài)為CommonScanningState。
掃描結果獲取
Supplicant執(zhí)行掃描成功后,調用WifiHalCbNotifyScanEnd(WPA_CB_SCAN_OVER_OK)通知掃描成功。ScanMonitor執(zhí)行回調,向ScanStateMachine發(fā)送SCAN_RESULT_EVENT事件:
```c++
void ScanMonitor::SendScanInfoEvent()
{
pScanStateMachine->SendMessage(static_cast<int>(SCAN_RESULT_EVENT));
return;
}
? ScanStateMachine此時狀態(tài)為CommonScanning,接收消息并處理,發(fā)起RPC遠程調用wifi hal獲取掃描結果。
```c++
case SCAN_RESULT_EVENT:
pScanStateMachine->CommonScanInfoProcess();
pScanStateMachine->SwitchState(pScanStateMachine->commonScanUnworkedState); //切換狀態(tài)為CommonScanUnworkedState
return true;
```c++
void ScanStateMachine::CommonScanInfoProcess()
{
WIFI_LOGI("Enter ScanStateMachine::CommonScanInfoProcess.
");
//構造ScanStatusReport
ScanStatusReport scanStatusReport;
//獲取掃描結果
if (!GetScanInfos(scanStatusReport.scanInfoList)) {
WIFI_LOGE("GetScanInfos failed.");
ReportCommonScanFailedAndClear(true);
return;
}
GetRunningIndexList(scanStatusReport.requestIndexList);
//設置掃描狀態(tài)為COMMON_SCAN_SUCCESS
scanStatusReport.status = COMMON_SCAN_SUCCESS;
if (scanStatusReportHandler) {
scanStatusReportHandler(scanStatusReport);
}
runningScans.clear();
return;
}
```c++
bool ScanStateMachine::GetScanInfos(std::vector<InterScanInfo> &scanInfos)
{
WIFI_LOGI("Enter ScanStateMachine::GetScanInfos.
");
WIFI_LOGI("Begin: QueryScanInfos.");
//發(fā)起RPC遠程調用wifi hal獲取掃描結果
if (WifiStaHalInterface::GetInstance().QueryScanInfos(scanInfos) != WIFI_IDL_OPT_OK) {
WIFI_LOGE("WifiStaHalInterface::GetInstance().GetScanInfos failed.");
return false;
}
WIFI_LOGI("End: QueryScanInfos.");
GetSecurityTypeAndBand(scanInfos);
return true;
}
WifiHal返回掃描結果給ScanStateMachine后,ScanStateMachine構造ScanStatusReport,包含scanInfoList和status為COMMON_SCAN_SUCCESS,通過scanStatusReportHandler上報,在ScanService::HandleScanStatusReport中處理。
```c++
oid ScanService::HandleScanStatusReport(ScanStatusReport &scanStatusReport)
{
WIFI_LOGI("Enter ScanService::HandleScanStatusReport.
");
switch (scanStatusReport.status) {
......
case COMMON_SCAN_SUCCESS: {
HandleCommonScanInfo(scanStatusReport.requestIndexList, scanStatusReport.scanInfoList);
break;
}
......
}
return;
}
ScanService拿到掃描結果,主要做的事是調用WifiSettings的SaveScanInfoList(filterScanInfo),將掃描結果保存。
之后,應用調用native js的GetScanInfos接口,通過WifiScanServiceImpl調用WifiSettings的GetScanInfoList獲取到保存的掃描結果。
掃描結果中包含的信息如下,一般常用到的信息有:
Bssid - 掃描到的AP的mac地址
Ssid - 掃描到的AP的標識名稱
Band - 支持頻段為2.4G還是5G
securityType - 安全類型: OPEN/WEP/PSK/SAE
```c++
struct WifiScanInfo {
std::string bssid;
std::string ssid;
/**
* Network performance, including authentication,
* key management, and encryption mechanisms
* supported by the access point
*/
std::string capabilities;
int frequency;
int band; /* ap band: 1 - 2.4GHZ, 2 - 5GHZ */
WifiChannelWidth channelWidth;
int centerFrequency0;
int centerFrequency1;
int rssi; /* signal level */
WifiSecurity securityType;
std::vector<WifiInfoElem> infoElems;
int64_t features;
int64_t timestamp;
}
連接流程
應用獲取到掃描結果后,選擇一個Wifi網(wǎng)絡進行連接,調用Native Js的connectToDevice接口調用到WifiDevice,然后通過IPC通信,WifiDeviceProxy作為客戶端代理發(fā)送WIFI_SVR_CMD_CONNECT2_TO消息,WifiDeviceStub作為服務端接收到消息后調用IPC服務的實現(xiàn)類WifiDeviceServiceImpl進行發(fā)起連接流程。
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_device_service_impl.cpp
```c++
ErrCode WifiDeviceServiceImpl::ConnectToDevice(const WifiDeviceConfig &config)
{
......
if (!IsStaServiceRunning()) {
return WIFI_OPT_STA_NOT_OPENED;
}
IStaService *pService = WifiServiceManager::GetInstance().GetStaServiceInst();
if (pService == nullptr) {
return WIFI_OPT_STA_NOT_OPENED;
}
return pService->ConnectToDevice(config); //調用StaService的ConnectToDevice
}
獲取StaService的接口實例,調用其ConnectToDevice方法。
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_service.cpp**
```c++
ErrCode StaService::ConnectToDevice(const WifiDeviceConfig &config) const
{
LOGI("Enter StaService::ConnectToDevice.
");
int netWorkId = AddDeviceConfig(config);//調用AddDeviceConfig
if(netWorkId == INVALID_NETWORK_ID) {
LOGD("StaService::ConnectTo AddDeviceConfig failed!");
return WIFI_OPT_FAILED;
}
LOGD("StaService::ConnectTo AddDeviceConfig succeed!");
pStaStateMachine->SendMessage(WIFI_SVR_CMD_STA_CONNECT_NETWORK, netWorkId, NETWORK_SELECTED_BY_THE_USER);//向StaStateMachine發(fā)送WIFI_SVR_CMD_STA_CONNECT_NETWORK消息
return WIFI_OPT_SUCCESS;
}
StaService首先調用AddDeviceConfig,在這個函數(shù)中主要做了兩件事:
1).調用GetNextNetworkId,通過HAL向supplicant發(fā)送ADD_NETWORK命令,得到netwrok id,保存在WifiDeviceConfig。
2)調用ConvertDeviceCfg,在StaStateMachine中將網(wǎng)絡配置參數(shù)轉換為idl參數(shù),然后調用HAL的SetDeviceConfig函數(shù),向supplicant發(fā)送SET_NETWORK命令。
StaService在調用AddDeviceConfig得到networkid并且設置配置參數(shù)到supplicant成功后,向StaStateMachine發(fā)送“WIFI_SVR_CMD_STA_CONNECT_NETWORK”消息,
目錄:foundation/communication/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_state_machine.cpp
StaStateMachine接收WIFI_SVR_CMD_STA_CONNECT_NETWORK消息調用DealConnectToUserSelectedNetwork
```c++
staSmHandleFuncMap[WIFI_SVR_CMD_STA_CONNECT_NETWORK] = &StaStateMachine::DealConnectToUserSelectedNetwork;
```c++
void StaStateMachine::DealConnectToUserSelectedNetwork(InternalMessage *msg)
{
LOGI("enter DealConnectToUserSelectedNetwork.
");
...... //一些狀態(tài)設置
StartConnectToNetwork(networkId); //開啟連接
}
StartConnectToNetwork:
```c++
void StaStateMachine::StartConnectToNetwork(int networkId)
{
targetNetworkId = networkId;
SetRandomMac(targetNetworkId); //設置隨機Mac
//EnableNetwork
if (WifiStaHalInterface::GetInstance().EnableNetwork(targetNetworkId) != WIFI_IDL_OPT_OK) {
LOGE("EnableNetwork() failed!");
return;
}
//Connect
if (WifiStaHalInterface::GetInstance().Connect(targetNetworkId) != WIFI_IDL_OPT_OK) {
LOGE("Connect failed!");
staCallback.OnStaConnChanged(OperateResState::CONNECT_SELECT_NETWORK_FAILED, linkedInfo);
return;
}
//SaveDeviceConfig
if (WifiStaHalInterface::GetInstance().SaveDeviceConfig() != WIFI_IDL_OPT_OK) {
LOGE("SaveDeviceConfig() failed!");
}
StopTimer(static_cast<int>(CMD_NETWORK_CONNECT_TIMEOUT));
StartTimer(static_cast<int>(CMD_NETWORK_CONNECT_TIMEOUT), STA_NETWORK_CONNECTTING_DELAY);
}
這里主要做了三個操作:發(fā)起RPC調用EnableNetwork,Connect,SaveDeviceConfig。
**目錄:foundation/communication/wifi/services/wifi_standard/wifi_hal/wifi_hal_sta_interface.c**
EnableNetwork:
```c
WifiErrorNo EnableNetwork(int networkId)
{
LOGD("EnableNetwork() networkid [%{public}d]", networkId);
WifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);
if (pStaIfc == NULL) {
return WIFI_HAL_SUPPLICANT_NOT_INIT;
}
int ret = pStaIfc->wpaCliCmdEnableNetwork(pStaIfc, networkId);
if (ret < 0) {
LOGE("WpaCliCmdEnableNetwork failed! ret=%{public}d", ret);
return WIFI_HAL_FAILED;
}
return WIFI_HAL_SUCCESS;
}
Connect:
WifiErrorNo Connect(int networkId)
{
LOGD("Connect() networkid %{public}d", networkId);
WifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);
if (pStaIfc == NULL) {
return WIFI_HAL_SUPPLICANT_NOT_INIT;
}
int ret = pStaIfc->wpaCliCmdSelectNetwork(pStaIfc, networkId);
if (ret < 0) {
LOGE("WpaCliCmdSelectNetwork failed! ret=%{public}d", ret);
return WIFI_HAL_FAILED;
}
return WIFI_HAL_SUCCESS;
}
SaveDeviceConfig:
WifiErrorNo SaveNetworkConfig(void)
{
LOGD("SaveNetworkConfig()");
WifiWpaStaInterface *pStaIfc = GetWifiStaInterface(0);
if (pStaIfc == NULL) {
return WIFI_HAL_SUPPLICANT_NOT_INIT;
}
int ret = pStaIfc->wpaCliCmdSaveConfig(pStaIfc);
if (ret < 0) {
LOGE("WpaCliCmdSaveConfig failed! ret=%{public}d", ret);
return WIFI_HAL_FAILED;
}
return WIFI_HAL_SUCCESS;
}
這里按調用先后向supplicant發(fā)送EnableNetwork、SELECT_NETWORK以及SAVE_CONFIG命令,supplicant根據(jù)收到的命令完成AP的連接管理。
Supplicant連接成功后,回送WPA_EVENT_CONNECTED事件,調用WifiHalCbNotifyConnectChanged(WPA_CB_CONNECTED,id,pMacPos)通知連接成功,經(jīng)過Hal再由StaMonitor的處理回調,發(fā)送消息WIFI_SVR_CMD_STA_NETWORK_CONNECTION_EVENT給StaStateMachine,調用DealConnectionEvent方法來處理連接事件,狀態(tài)機進入getIpState狀態(tài),獲取ip地址,靜態(tài)ip或者dhcp動態(tài)獲取成功后,繼續(xù)調用StaNetworkCheck檢查網(wǎng)絡連接狀態(tài)。
Wifi-STA接口說明及使用
接口說明
WLAN基礎功能由@ohos.wifi類提供,其接口(JS接口)說明如下。
表 1 WLAN功能接口(JS接口)
接口名 | 描述 |
---|---|
function enableWifi(): boolean | 打開WLAN。 |
function disableWifi(): boolean | 關閉WLAN。 |
function isWifiActive(): boolean | 查詢WLAN是否處于打開狀態(tài)。 |
function scan(): boolean | 發(fā)起WLAN掃描。 |
function getScanInfos(): Promise<Array<WifiScanInfo>>;<br/>function getScanInfos(callback: AsyncCallback<Array<WifiScanInfo>>): void; | 獲取WLAN掃描結果,接口可采用promise或callback方式調用。 |
function addDeviceConfig(config: WifiDeviceConfig): Promise<number>;<br/>function addDeviceConfig(config: WifiDeviceConfig, callback: AsyncCallback<number>): void; | 添加WLAN熱點的配置信息,接口可采用promise或callback方式調用。 |
function connectToNetwork(networkId: number): boolean | 連接到WLAN網(wǎng)絡。(一般為隱藏熱點的連接) |
function connectToDevice(config: WifiDeviceConfig): boolean | 連接到WLAN網(wǎng)絡。 |
function disconnect(): boolean | 斷開WLAN連接。 |
function getSignalLevel(rssi: number, band: number): number | 獲取WLAN信號強度。 |
function getLinkedInfo(): Promise<WifiLinkedInfo>;<br/>function getLinkedInfo(callback: AsyncCallback<WifiLinkedInfo>): void; | 獲取WLAN連接信息接口可采用promise或callback方式調用。 |
function isConnected(): boolean; | 查詢是否是連接狀態(tài)。 |
function getSupportedFeatures(): number; | 獲取設備支持的feature。 |
function isFeatureSupported(featureId: number): boolean; | 查詢設備是否支持指定feature。 |
function getDeviceMacAddress(): string[]; | 獲取MAC地址。 |
function getIpInfo(): IpInfo; | 獲取IP。 |
function getCountryCode(): string; | 獲取國家碼。 |
function reassociate(): boolean; | 重新連接當前網(wǎng)絡。 |
function reconnect(): boolean; | 重新連接當前Wifi。 |
function getDeviceConfigs(): Array<WifiDeviceConfig>; | 獲取現(xiàn)存的Wifi列表。 |
function updateNetwork(config: WifiDeviceConfig): number; | 更新指定的Wifi配置。 |
function disableNetwork(netId: number): boolean; | 關閉指定的網(wǎng)絡。 |
function removeAllNetwork(): boolean; | 移除所有的網(wǎng)絡。 |
function removeDevice(id: number): boolean; | 刪除指定ID的網(wǎng)絡。 |
表 1 WLAN事件接口(JS接口)
接口名 | 描述 |
---|---|
function on(type: "wifiStateChange", callback: Callback<number>): void;<br/>function off(type: "wifiStateChange", callback?: Callback<number>): void; | Wifi狀態(tài)監(jiān)聽事件 |
function on(type: "wifiConnectionChange", callback: Callback<number>): void;<br/>function off(type: "wifiConnectionChange", callback?: Callback<number>): void; | Wifi連接狀態(tài)監(jiān)聽 |
function on(type: "wifiScanStateChange", callback: Callback<number>): void;<br/>function off(type: "wifiScanStateChange", callback?: Callback<number>): void; | Wifi掃描狀態(tài)監(jiān)聽 |
function on(type: "wifiRssiChange", callback: Callback<number>): void;<br/>function off(type: "wifiRssiChange", callback?: Callback<number>): void; | Wifi信號監(jiān)聽 |
更多原創(chuàng)內容請關注:深開鴻技術團隊
入門到精通、技巧到案例,系統(tǒng)化分享HarmonyOS開發(fā)技術,歡迎投稿和訂閱,讓我們一起攜手前行共建鴻蒙生態(tài)。
本文摘自 :https://blog.51cto.com/h