函数实现详解
减少引用数
static int Release(IUnknown *proxy)
{
MUTEX_Lock(g_mutex);
int ref = IUNKNOWN_Release(proxy);
MUTEX_Unlock(g_mutex);
if (ref != 0) {
return ref;
}
IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
int ret = SAMGR_ReleaseIClient(client->header.key.service, client->header.key.feature, client);
if (ret == EC_NOHANDLER) {
SAMGR_Free(client);
return EC_SUCCESS;
}
return ret;
}
客户端代理的处理函数
/*
函数功能:负责客户端代理请求消息的发送和响应消息的接收
函数参数:@proxy:客户端代理
@funcId:指定调用的服务端处理函数
@request:待发送的请求消息
@owner:请求消息的创建者
@notify:响应消息的处理者
函数描述:将客户端代理创建的请求消息发送给指定的服务和功能。
若notify为NULL则不需要接收响应消息,若notify不为NULL则需要接收响应消息。
notify将响应消息转发给对应的客户端代理。
*/
static int ProxyInvoke(IClientProxy *proxy, int funcId, IpcIo *request, IOwner owner, INotify notify)
{
if (proxy == NULL) {
return EC_INVALID
}
//获取代理接口的IDefaultClient成员
IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown)
//获取头部信息
IClientHeader *header = &client->header
if (header->target.handle == INVALID_INDEX) {
//目标的访问地址是无效的,需要重新获取访问地址
header->target = QueryIdentity(header->context, header->key.service, header->key.feature)
if (header->target.handle == INVALID_INDEX) {
//重新查询后还是无效,则返回EC_INVALID
return EC_INVALID
}
//查询成功,注册死亡回调函数
(void)RegisterDeathCallback(header->context, header->target, OnServiceExit, header, &header->deadId)
}
//构建响应消息体
IpcIo reply
void *replyBuf = NULL
/*
LITEIPC_FLAG_DEFAULT 发送并且服务端需要响应
LITEIPC_FLAG_ONEWAY 仅发送消息
*/
//若notify不为NULL,则指定flag为LITEIPC_FLAG_DEFAULT,发送并且服务端需要响应。notify接收响应消息并转发给响应的owner
IpcFlag flag = (notify == NULL) ? LITEIPC_FLAG_ONEWAY : LITEIPC_FLAG_DEFAULT
//从当前进程的endpoint向目标的地址发送请求消息
int ret = Transact(header->context, header->target, funcId, request, &reply, flag, (uintptr_t *)&replyBuf)
if (ret != LITEIPC_OK) {//发送失败
//解除死亡的回调函数
(void)UnregisterDeathCallback(header->target, header->deadId)
//清除访问地址信息,返回EC_FAILURE
header->deadId = INVALID_INDEX
header->target.handle = INVALID_INDEX
header->target.token = INVALID_INDEX
header->target.cookie = INVALID_INDEX
return EC_FAILURE
}
//请求消息发送成功
//判断notify是否为NULL,用于接收响应消息,并转发给对应的请求消息创建者
if (notify != NULL) {
/*
owner表示接收响应数据的客户端代理,也是请求消息的创建者
*/
//通知owner处理响应消息
notify(owner, ret, &reply)
}
if (replyBuf != NULL) {//资源回收
FreeBuffer(header->context, replyBuf)
}
return ret
}
断开服务的回调函数
/*
函数功能:断开连接后回收资源
函数参数:@context:IPC通信上下文
@ipcMsg:消息IO
@data:数据缓冲区
@argv:客户端代理,由调用者指定
函数描述:与服务断开连接时触发的回调函数,负责回收持有的资源。
*/
static int OnServiceExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv)
{
(void)data
//获取头部
IClientHeader *header = (IClientHeader *)argv
//解除死亡回调函数
(void)UnregisterDeathCallback(header->target, header->deadId)
BinderRelease(context, header->target.handle)
//清空,置为无效值
header->deadId = INVALID_INDEX
header->target.handle = INVALID_INDEX
header->target.token = INVALID_INDEX
header->target.cookie = INVALID_INDEX
if (ipcMsg != NULL) {
//回收资源
FreeBuffer(header->context, ipcMsg)
}
HILOG_ERROR(HILOG_MODULE_SAMGR, "Miss the remote service<%u, %u>!", header->target.handle, header->target.token)
return EC_SUCCESS
}
DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案)
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
获取服务和功能的访问地址
static SvcIdentity QueryIdentity(const IpcContext *context, const char *service, const char *feature)
{
IpcIo req;
uint8 data[MAX_DATA_LEN];
IpcIoInit(&req, data, MAX_DATA_LEN, 0);
IpcIoPushUint32(&req, RES_FEATURE);
IpcIoPushUint32(&req, OP_GET);
IpcIoPushString(&req, service);
IpcIoPushBool(&req, feature == NULL);
if (feature != NULL) {
IpcIoPushString(&req, feature);
}
IpcIo reply;
void *replyBuf = NULL;
SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
int ret = Transact(context, samgr, INVALID_INDEX, &req, &reply, LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf);
ret = (ret != LITEIPC_OK) ? EC_FAILURE : IpcIoPopInt32(&reply);
SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
if (ret == EC_SUCCESS) {
SvcIdentity *svc = IpcIoPopSvc(&reply);
if (svc != NULL) {
#ifdef __LINUX__
BinderAcquire(svc->ipcContext, svc->handle);
#endif
target = *svc;
}
}
if (ret == EC_PERMISSION) {
HILOG_INFO(HILOG_MODULE_SAMGR, "Cannot Access<%s, %s> No Permission!", service, feature);
}
if (replyBuf != NULL) {
FreeBuffer(context, replyBuf);
}
return target;
}