文章目录
1. JS 到 Native JS ---- NAPI 通信
1.1WIFI的native js目录结构
├── js
│ └── napi // js 和 c++ 通信
│ ├── inc
│ └── src
└── native
├── c_adapter
│ ├── inc
│ └── src
├── include
├── interfaces
└── src
1.2 js 与 c++方法绑定
communication\wifi\interfaces\innerkits\native_cpp\napi\wifi_napi_entry.cpp
namespace OHOS {
namespace Wifi {
#ifndef ENABLE_NAPI_COMPATIBLE
/*
* Module initialization function
*/
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("enableWifi", EnableWifi), //
DECLARE_NAPI_FUNCTION("disableWifi", DisableWifi),
DECLARE_NAPI_FUNCTION("isWifiActive", IsWifiActive),
// ... 绑定函数
};
// 将desc中设置到export中
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
return exports;
}
// 1. 创建module
static napi_module wifiJsModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = NULL,
.nm_register_func = Init, // 2. 注册函数表
.nm_modname = "wifi", // module name
.nm_priv = ((void *)0),
.reserved = { 0 }
};
// 3. 注册module
extern "C" __attribute__((constructor)) void RegisterModule(void) {
napi_module_register(&wifiJsModule);
}
} // namespace Wifi
} // namespace OHOS
napi_value EnableWifi(napi_env env, napi_callback_info info)
{
TRACE_FUNC_CALL;
NAPI_ASSERT(env, wifiDevicePtr != nullptr, "Wifi device instance is null.");
ErrCode ret = wifiDevicePtr->EnableWifi();
WriteWifiStateHiSysEvent(HISYS_SERVICE_TYPE_STA, WifiOperType::ENABLE);
napi_value result;
napi_get_boolean(env, ret == WIFI_OPT_SUCCESS, &result);
return result;
}
1.3 .d.ts文件声明
/**
* Provides methods to operate or manage Wi-Fi.
*
* @since 6
* @import import wifi from '@ohos.wifi';
*/
declare namespace wifi {
function enableWifi(): boolean;
function disableWifi(): boolean;
function isWifiActive(): boolean;
function scan(): boolean;
function getScanInfos(): Promise<Array<WifiScanInfo>>;
// ...
}
export default wifi;
OpenHarmony 源码解析之JavaScript API框架(NAPI)-开源基础软件社区-51CTO.COM
2. Native——FWK IPC通信-----Remote()
#过年不停更# Openharmony IPC通信(L2)-开源基础软件社区-51CTO.COM
2.1 Binder通信
Remote() 封装的 binder 通信
Android | OHOS |
---|---|
SeviceManager管理 | SystemAbilityManagerClient管理 |
service自己注册到binder | 需要手动注册到binder |
只需要关注方法和参数,其余aidl自动生成 | 需要自己手写逻辑 |
binder aidl 生成文件
// 客户端发请求
@Override
public void addPerson(Person person) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(DESCRIPTOR);// 1. 写入binder标识
if (null != person) {
data.writeInt(1);
person.writeToParcel(data, 0); // 2. 写入数据
} else {
data.writeInt(0);
}
mRemote.transact(TRANSACTION_addPerson, data, reply, 0);// 3. 发消息
reply.readException();
} finally {
data.recycle();
reply.recycle();
}
}
// 服务端接收请求
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
case TRANSACTION_addPerson:
data.enforceInterface(DESCRIPTOR);
Person arg0;
if (0 != data.readInt()) {
arg0 = (Person) Person.CREATOR.createFromParcel(data);
} else {
arg0 = null;
}
this.addPerson(arg0);
reply.writeNoException();
return true;
case TRANSACTION_getPersonList:
data.enforceInterface(DESCRIPTOR);
List<Person> result = getPersonList();
reply.writeNoException();
reply.writeTypedList(result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
Remote 写法
// 发送请求
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;
//1. 写入binder标识
// DECLARE_INTERFACE_DESCRIPTOR(u"ohos.wifi.IWifiDeviceService");
if (!data.WriteInterfaceToken(GetDescriptor())) {
WIFI_LOGE("Write interface token error: %{public}s", __func__);
return WIFI_OPT_FAILED;
}
//2. 写入数据
data.WriteInt32(0);
//3. 向服务端发消息 WIFI_SVR_CMD_ENABLE_WIFI
int error = Remote()->SendRequest(WIFI_SVR_CMD_ENABLE_WIFI, data, reply, option);
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());
}
// 处理请求
int WifiDeviceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
if (data.ReadInterfaceToken() != GetDescriptor()) {
WIFI_LOGE("Sta stub token verification error");
return WIFI_OPT_FAILED;
}
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;
}
2.2 服务端注册
注册方式1
基本上自己有main函数入口:
xxxService继承IPCObjectStub 和 xxxInterface
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> newInstance = new xxxService();
int result = saMgr->AddSystemAbility(xxxSaId, newInstance);
注册方式2
本身没有main函数入口,需要借助safwk的main入口:
xxxService继承IPCObjectStub,xxxInterface 和 SystemAbility
// 注册方式2的第一种方式
REGISTER_SYSTEM_ABILITY_BY_ID(xxxService, xxxSaId, true); // 添加ability信息
Publish(this); // 在重写的OnStart函数中调用,注册到samgr中
// 注册方式2的第二种方式
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(WifiDeviceServiceImpl::GetInstance().GetRefPtr());
Publish(this)
// WifiDeviceService 注册
const bool REGISTER_RESULT = SystemAbility::MakeAndRegisterAbility(WifiDeviceServiceImpl::GetInstance().GetRefPtr());
WifiDeviceServiceImpl::WifiDeviceServiceImpl()
#ifdef OHOS_ARCH_LITE
: mPublishFlag(false), mState(ServiceRunningState::STATE_NOT_START)
#else
: SystemAbility(WIFI_DEVICE_ABILITY_ID, true), mPublishFlag(false), mState(ServiceRunningState::STATE_NOT_START)
#endif
{}
2.3 客户端类定义
xxxServiceProxy继承PeerHolder 和 xxxInterface
客户端类中定义一个静态变量:
// 定义静态变量,才能通过iface_cast创建一个包含IPCObjectProxy的xxxServiceProxy对象
static inline BrokerDelegator<xxxServiceProxy> delegator_;
2.4 客户端获取注册信息
auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> object = saMgr->GetSystemAbility(SaId);
client = iface_cast<xxxInterface >(object);
// WIFI Device范例
std::unique_ptr<OHOS::Wifi::WifiDevice> wifiDevicePtr = OHOS::Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
bool WifiDeviceImpl::Init()
{
sptr<ISystemAbilityManager> sa_mgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
sptr<IRemoteObject> object = sa_mgr->GetSystemAbility(systemAbilityId_);
client_ = iface_cast<IWifiDevice>(object);
// ...
}
// 服务id配置
distributedschedule\samgr\interfaces\innerkits\samgr_proxy\include\system_ability_definition.h
enum {
// ...
WIFI_DEVICE_SYS_ABILITY_ID = 1120,
WIFI_HOTSPOT_SYS_ABILITY_ID = 1121,
WIFI_ENHANCER_SYS_ABILITY_ID = 1122,
WIFI_P2P_SYS_ABILITY_ID = 1123,
// ...
}
static const std::map<int, std::string> saNameMap_ = {
{ 200, "AccountMgr" },
{ 301, "AIEngine" },
{ BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, "BundleMgr" },
{ FORM_MGR_SERVICE_ID, "FormMgr" },
{ WIFI_DEVICE_SYS_ABILITY_ID, "WifiDevice" },
{ WIFI_HOTSPOT_SYS_ABILITY_ID, "WifiHotspot" },
{ WIFI_ENHANCER_SYS_ABILITY_ID, "WifiEnhancer" },
{ WIFI_P2P_SYS_ABILITY_ID, "WifiP2p" },
// ...
}
3. FWK——HAL Socket 通信
Linux Socket编程(不限Linux) - 吴秦 - 博客园 (cnblogs.com)
使用一个.sock为后缀的文件来进行进程间通信,写入就是发送请求,读取就是接受该请求的返回信息.
Server端
wifi/wifi/services/wifi_standard/wifi_hal/main.c
int main(void)
{
LOGI("Wifi hal service starting...");
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); // 二、建立Socket通信
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);
SendStartNotify();
RunRpcLoop(server); // 三、进入事件循环
/* stop wpa_supplicant, hostapd, and other resources */
ForceStop();
for (int id = 0; id < AP_MAX_INSTANCE; id++) {
StopSoftAp(id);
}
P2pForceStop();
ReleaseWifiHalVendorInterface();
/* clear RPC Server */
SetRpcServerInited(NULL);
ReleaseRpcServer(server);
ReleaseRpcFunc();
LOGI("hal service exists!");
return 0;
}
二、建立Socket通信
RpcServer *CreateRpcServer(const char *path)
{
RpcServer *server = (RpcServer *)calloc(1, sizeof(RpcServer));
int flag = 1;
do {
int ret = CreateUnixServer(path, DEFAULT_LISTEN_QUEUE_SIZE); // CreateUnixServer,建立socket通信
server->listenFd = ret;
server->loop = CreateEventLoop(MAX_SUPPORT_CLIENT_FD_SIZE); // 创建loop监听事件
// ...
} while (0);
if (flag) {
ReleaseRpcServer(server);
return NULL;
}
return server;
}
int CreateUnixServer(const char *path, int backlog)
{
struct sockaddr_un sockAddr;
if (memset_s(&sockAddr, sizeof(sockAddr), 0, sizeof(sockAddr)) != EOK) {
return -1;
}
sockAddr.sun_family = AF_LOCAL;
if (strncpy_s(sockAddr.sun_path, sizeof(sockAddr.sun_path), path, strlen(path)) != EOK) {
return -1;
}
int sock = CreateSocket(AF_LOCAL); // 创建socket int sock = socket(domain, SOCK_STREAM, 0);
if (sock < 0) {
return -1;
}
int keepAlive = 1;
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
int reuseaddr = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&reuseaddr, sizeof(reuseaddr));
// 绑定"/data/misc/wifi/unix_sock.sock"并进行监听 1.bind 2. listen
if (bind(sock, (struct sockaddr *)&, sizeof(sockAddr)) < 0) {
}
if (SetNonBlock(sock, 1) != 0) {
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
if (listen(sock, backlog) < 0) {
}
return sock;
}
三、进行事件循环
int RunRpcLoop(RpcServer *server)
{
if (server == NULL) {
return -1;
}
EventLoop *loop = server->loop;
while (!loop->stop) {
BeforeLoop(server);
int retval = epoll_wait(loop->epfd, loop->epEvents, loop->setSize, 5); // wait 5ms
for (int i = 0; i < retval; ++i) {
struct epoll_event *e = loop->epEvents + i;
int fd = e->data.fd;
unsigned int mask = CheckEventMask(e);
if (fd == server->listenFd) {
OnAccept(server, mask); // 接收事件: int fd = accept(server->listenFd, NULL, NULL);
} else {
DealFdEvents(server, fd, mask);
}
}
}
return 0;
}
总结:
1.int socket(int domain, int type, int protocol); 创建socket
2.int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 绑定
3.int listen(int sockfd, int backlog); 监听
4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 接收请求
Client 端
int WifiIdlClient::InitClient(void)
{
const std::string idlSockPath = "/data/misc/wifi/unix_sock.sock"; // .sock文件
pRpcClient = CreateRpcClient(idlSockPath.c_str()); // call CreateRpcClient
// ...
}
RpcClient *CreateRpcClient(const char *path)
{
int fd = ConnectUnixServer(path); // 连接socket
SetNonBlock(fd, 1);
RpcClient *client = (RpcClient *)calloc(1, sizeof(RpcClient));
// ...
client->context = CreateContext(CONTEXT_BUFFER_MIN_SIZE);
// ...
int ret = pthread_create(&client->threadId, NULL, RpcClientThreadDeal, client);
// ...
signal(SIGPIPE, SIG_IGN);
return client;
}
int ConnectUnixServer(const char *path)
{
// ...
sockAddr.sun_family = AF_LOCAL;
if (strncpy_s(sockAddr.sun_path, sizeof(sockAddr.sun_path), path, strlen(path)) != EOK) {
return -1;
}
// 1.创建socket
int sock = CreateSocket(AF_LOCAL); // int sock = socket(domain, SOCK_STREAM, 0);
if (sock < 0) {
return -1;
}
// 2.链接socket
if (connect(sock, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) < 0) {
LOGE("connect failed!");
close(sock);
return -1;
}
return sock;
}
- int socket(int domain, int type, int protocol);
- int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
client发消息到Server
WifiErrorNo Start(void)
{
RpcClient *client = GetStaRpcClient();
LockRpcClient(client);
Context *context = client->context;
WriteBegin(context, 0);
WriteFunc(context, "Start"); // 写入context->szWrite
WriteEnd(context);
if (RpcClientCall(client, "Start") != WIFI_IDL_OPT_OK) { // 发送事件到Server
return WIFI_IDL_OPT_FAILED;
}
int result = WIFI_IDL_OPT_FAILED;
ReadInt(context, &result);
ReadClientEnd(client);
UnlockRpcClient(client);
return result;
}
int RemoteCall(RpcClient *client)
{
// ...
Context *context = client->context;
while (context->wBegin != context->wEnd && ret >= 0) {
ret = ContextWriteNet(context);
}
if (ret < 0) {
return ret;
}
ret = 0; /* reset ret value */
pthread_mutex_lock(&client->mutex);
while (client->waitReply != CLIENT_STATE_DEAL_REPLY && client->waitReply != CLIENT_STATE_EXIT) {
pthread_cond_wait(&client->condW, &client->mutex);
}
if (client->waitReply == CLIENT_STATE_EXIT) {
ret = -1;
}
pthread_mutex_unlock(&client->mutex);
return ret;
}
int ContextWriteNet(Context *context)
{
if (context->wBegin < context->wEnd) {
int ret = MyWrite(context->fd, context->szWrite + context->wBegin, context->wEnd - context->wBegin);// 写入事件int ret = write(fd, buf + pos, count);
if (ret > 0) {
context->wBegin += ret;
}
return ret;
}
// ...
return ret;
}
Server端接收
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;
}
// socket error
LOGE("%s: error on socket(): %d = %s", __func__, errno, strerror(errno));