往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony轻量系统服务管理|samgr_server功能详解(一)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(二)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(三)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(四)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(五)
- OpenHarmony轻量系统服务管理|samgr_server功能详解(六)
- OpenHarmony分布式调度详解|dmslite.c
- OpenHarmony分布式调度详解|dmslite_feature.c 源码阅读
- OpenHarmony分布式调度详解|dmslite_session.c
- OpenHarmony分布式调度详解|dmslite_tlv_common.c
- OpenHarmony分布式调度详解|dmslite_famgr.c
- 持续更新中……
前言
foundation\distributedschedule\dmsfwk_lite\source\adapter\dms\dmslite_famgr.c文件中主要包含一些启动FA的函数和操作。
代码分析
获取ams和Feature接口
/**
* 函数功能:ams结果回调函数
* 函数参数:
* context:Ipc上下文
* ipcMsg:Ipc消息
* io:IpcIo信息
* arg:参数。该函数中没有用到,在调用此函数的地方也把该参数设为NULL
* 函数返回值:
* 成功,返回0;否则返回-10
*/
static int32_t AmsResultCallback(const IpcContext* context, void *ipcMsg, IpcIo *io, void *arg)
{
/* Notice: must free ipcMsg, for we don't need ipcMsg here, just free it at first */
FreeBuffer(context, ipcMsg); // 释放ipcMsg所占空间
HILOGD("[AmsResultCallback called]");
if (g_onStartAbilityDone == NULL) { // 如果为空,返回无效参数错误码
return LITEIPC_EINVAL;
}
ElementName elementName; // 创建一个ElementName结构体对象,并将其填充为0,包含设备名、包名、ability名
if (memset_s(&elementName, sizeof(ElementName), 0x00, sizeof(ElementName)) != EOK) {
HILOGE("[elementName memset failed]");
return LITEIPC_EINVAL;
}
/* the element is not used so far, and deserialize element first before we can get the errcode from io */
if (!DeserializeElement(&elementName, io)) { // 对elementName进行反序列化
return LITEIPC_EINVAL;
}
ClearElement(&elementName);
int8_t errCode = DMS_EC_START_ABILITY_ASYNC_FAILURE; // errCode默认设为启动失败错误码
if (IpcIoPopInt32(io) == EC_SUCCESS) { // FA成功启动并显示在屏幕上
/* this means that FA starts and shows on screen successfully */
errCode = DMS_EC_START_ABILITY_ASYNC_SUCCESS;
}
g_onStartAbilityDone(errCode);
return LITEIPC_OK;
}
/**
* 函数功能:获取ams的api接口
* 函数参数:
* amsInterface:ams接口对象
* 函数返回值:
* 成功,返回true;否则返回false
*/
static bool GetAmsInterface(struct AmsInterface **amsInterface)
{
// 通过SAMGR获取ams的FeatureApi接口得到iUnknown对象
IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(AMS_SERVICE, AMS_FEATURE);
if (iUnknown == NULL) {
HILOGE("[GetFeatureApi failed]");
return false;
}
// 通过QueryInterface获取amsInterface接口
int32_t errCode = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void**) amsInterface);
if (errCode != EC_SUCCESS) {
HILOGE("[QueryInterface failed]");
return false;
}
return true;
}
/**
* 函数功能:填充Want信息,包括需要启动的FA的包名和ability名
* 函数参数:
* want:要填充的want结构体对象
* bundleName:要启动的FA的包名
* abilityName:要启动的FA的ability名
* 函数返回值:
* 成功,返回0;否则返回非0
*/
static int32_t FillWant(Want *want, const char *bundleName, const char *abilityName)
{
if (memset_s(want, sizeof(Want), 0x00, sizeof(Want)) != EOK) { // 将Want结构体填充为0
HILOGE("[want memset failed]");
return DMS_EC_FAILURE;
}
ElementName element; // 构造一个临时的ElementName结构体对象,并将其填充为0
if (memset_s(&element, sizeof(ElementName), 0x00, sizeof(ElementName)) != EOK) { // 将ElementName填充为0
HILOGE("[elementName memset failed]");
return DMS_EC_FAILURE;
}
if (!(SetElementBundleName(&element, bundleName) // 将bundleName设置到element中
&& SetElementAbilityName(&element, abilityName) // 将abilityName设置到element中
&& SetWantElement(want, element) // 将element设置到want中
&& SetWantSvcIdentity(want, g_serviceIdentity))) { // 设置want的identity
HILOGE("[Fill want failed]");
ClearElement(&element);
ClearWant(want);
return DMS_EC_FAILURE;
}
ClearElement(&element);
return DMS_EC_SUCCESS;
}
远程启动FA设备
/**
* 函数功能:从远端内部启动ability
* 函数参数:
* bundleName:包名称
* abilityName:ability名称
* 函数返回值:
* 成功返回值1,否则返回其他错误码
*/
static int32_t StartAbilityFromRemoteInner(const char *bundleName, const char *abilityName)
{
Want want; /* NOTICE: must call ClearWant if filling want sucessfully */
if (FillWant(&want, bundleName, abilityName) != DMS_EC_SUCCESS) { // 构造Want对象,用于在不同ability之间传递信息
return DMS_EC_FILL_WANT_FAILURE;
}
int32_t errCode;
uid_t callerUid = getuid(); // 获取当前调用者的uid
if (callerUid == FOUNDATION_UID) { // 如果为FOUNDATION用户,则是进程内调用
/* inner-process mode */
struct AmsInterface *amsInterface = NULL;
if (!GetAmsInterface(&amsInterface)) { // 拿到ams的Feature接口,并调用启动FA
HILOGE("[GetAmsInterface query null]");
ClearWant(&want);
return DMS_EC_GET_AMS_FAILURE;
}
errCode = amsInterface->StartAbility(&want);
} else if (callerUid == SHELL_UID) { // 如果为SHELL用户,则是进程间调用
/* inter-process mode (mainly called in xts testsuit process started by shell) */
errCode = StartAbility(&want);
} else {
errCode = EC_FAILURE;
}
ClearWant(&want);
if (errCode != EC_SUCCESS) { // 如果errCode不为0,调用StartAbility启动FA失败
HILOGE("[Call ams StartAbility failed errCode = %d]", errCode);
return DMS_EC_START_ABILITY_SYNC_FAILURE;
}
/* this just means we send to the ams a request of starting FA successfully */
// 这意味着我们向ams发送了一个成功启动FA的请求
return DMS_EC_START_ABILITY_SYNC_SUCCESS;
}
/**
* 函数功能:远程启动ability
* 函数参数:
* bundleName:包名称
* abilityName:ability名称
* onStartAbilityDone:启动ability的回调函数
* 函数返回值:
* 成功返回0;否则返回非0
*/
int32_t StartAbilityFromRemote(const char *bundleName, const char *abilityName,
StartAbilityCallback onStartAbilityDone)
{
if (bundleName == NULL || abilityName == NULL) { // 检查参数的有效性
HILOGE("[Invalid parameters]");
return DMS_EC_FAILURE;
}
if (g_serviceIdentity.token == INVALID_IPC_TOKEN) { // 判断全局服务id的token是否有效
/* register a callback for notification when ams starts ability successfully */
// 当ams启动ability成功时,注册一个回调
IpcCbMode mode = ONCE; // 采用及时模式
if (RegisterIpcCallback(AmsResultCallback, mode, IPC_WAIT_FOREVER,
&g_serviceIdentity, NULL) != EC_SUCCESS) {
HILOGE("[RegisterIpcCallback failed]");
return DMS_EC_REGISTE_IPC_CALLBACK_FAILURE;
}
}
if (g_onStartAbilityDone == NULL) { // 如果g_onStartAbilityDone为NULL,则将其赋值为onStartAbilityDone回调
g_onStartAbilityDone = onStartAbilityDone;
}
return StartAbilityFromRemoteInner(bundleName, abilityName);
}
/**
* 函数功能:启动远程ability
* 函数参数:
* want:操作ability和携带的额外数据的信息
* 函数返回值:
* 成功,返回0;否则返回非0
*/
int32_t StartRemoteAbility(const Want *want)
{
HILOGE("[StartRemoteAbility]"); // 打印启动ability日志信息
if (want == NULL || want->data == NULL || want->element == NULL) { // 检查参数有效性
return DMS_EC_INVALID_PARAMETER;
}
char *bundleName = (char *)want->data; // 从want中获取包名
BundleInfo bundleInfo; // 声明一个BundleInfo对象,用来保存包信息
if (memset_s(&bundleInfo, sizeof(BundleInfo), 0x00, sizeof(BundleInfo)) != EOK) { // 初始化bundleInfo,填充为0
HILOGE("[bundleInfo memset failed]");
return DMS_EC_FAILURE;
}
GetBundleInfo(bundleName, 0, &bundleInfo); // 获取包信息
#ifndef XTS_SUITE_TEST
PreprareBuild();
#endif
// 以下几行代码判断相关字段是否已经转换为对应的数据类型
PACKET_MARSHALL_HELPER(Uint16, COMMAND_ID, DMS_MSG_CMD_START_FA);
PACKET_MARSHALL_HELPER(String, CALLEE_BUNDLE_NAME, want->element->bundleName);
PACKET_MARSHALL_HELPER(String, CALLEE_ABILITY_NAME, want->element->abilityName);
if (bundleInfo.appId != NULL) {
PACKET_MARSHALL_HELPER(String, CALLER_SIGNATURE, bundleInfo.appId);
} else {
PACKET_MARSHALL_HELPER(String, CALLER_SIGNATURE, "");
}
PACKET_MARSHALL_HELPER(Uint16, DMS_VERSION, DMS_VERSION_VALUE);
HILOGE("[StartRemoteAbility len:%d]", GetPacketSize());
#ifndef XTS_SUITE_TEST
return SendDmsMessage(GetPacketBufPtr(), GetPacketSize()); // 向dms发送消息
#else
return EOK;
#endif
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: