Foundation 进程 IPC 接口方法添加步骤指南
本文档详细说明了在 Foundation 进程中添加新 IPC 接口方法的完整流程。
Foundation 进程架构
- 系统能力 ID: SA 401
- 接口类:
IBundleMgr - 接口描述符:
u"ohos.appexecfwk.BundleMgr" - 用途: 核心业务逻辑、Bundle 信息管理、权限控制
文件清单
需要修改的文件(共 8 个):
interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h- 接口方法声明interfaces/inner_api/appexecfwk_core/include/bundle_framework_core_ipc_interface_code.h- 接口代码枚举interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_proxy.h- Proxy 类定义interfaces/inner_api/appexecfwk_core/src/bundlemgr/bundle_mgr_proxy.cpp- Proxy 实现interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_host.h- Host 类定义interfaces/inner_api/appexecfwk_core/src/bundlemgr/bundle_mgr_host.cpp- Host case 处理services/bundlemgr/include/bundle_mgr_host_impl.h- 业务实现类定义services/bundlemgr/src/bundle_mgr_host_impl.cpp- 业务逻辑实现
完整实现步骤
第二步:添加接口方法声明
文件: interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h
在 IBundleMgr 类中添加方法声明:
class IBundleMgr : public IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.BundleMgr");
// ... 现有方法
/**
* @brief 获取自定义 Bundle 信息
* @param bundleName Bundle 名称
* @param userId 用户 ID
* @param customInfo 输出参数,自定义信息
* @return 成功返回 ERR_OK,失败返回错误码
*/
virtual ErrCode GetCustomBundleInfo(const std::string &bundleName,
int32_t userId, CustomInfo &customInfo) = 0;
};
第三步:添加接口代码枚举
文件: interfaces/inner_api/appexecfwk_core/include/bundle_framework_core_ipc_interface_code.h
查看现有枚举值,使用下一个未使用的编号:
enum class BundleMgrInterfaceCode : uint32_t {
// ... 现有代码
GET_BUNDLE_INSTALL_STATUS = 211,
GET_ALL_JSON_PROFILE = 212,
GET_BUNDLE_INFO_FOR_EXCEPTION = 213,
BATCH_GET_COMPATIBLED_DEVICE_TYPE = 214,
GET_ALL_APP_PROVISION_INFO = 215,
ADD_DYNAMIC_SHORTCUT_INFOS = 216,
DELETE_DYNAMIC_SHORTCUT_INFOS = 217,
GET_ASSET_GROUPS_INFOS_BY_UID = 218,
SET_SHORTCUTS_ENABLED = 219,
GET_PLUGIN_EXTENSION_INFO = 220,
AUTO_CLEAN_CACHE_BY_INODE = 221,
GET_ALL_APP_INSTALL_EXTENSION_INFO = 222,
IS_APPLICATION_DISABLE_FORBIDDEN = 223,
GET_CUSTOM_BUNDLE_INFO = 224, // 新增 - 使用下一个可用的编号
};
第四步:实现 Proxy
4.1 在 bundle_mgr_proxy.h 中添加方法声明
文件: interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_proxy.h
class BundleMgrProxy : public IRemoteProxy<IBundleMgr> {
public:
explicit BundleMgrProxy(const sptr<IRemoteObject> &impl);
virtual ~BundleMgrProxy() override;
// ... 现有方法声明
// 新增方法
ErrCode GetCustomBundleInfo(const std::string &bundleName,
int32_t userId, CustomInfo &customInfo) override;
};
4.2 在 bundle_mgr_proxy.cpp 中实现方法
文件: interfaces/inner_api/appexecfwk_core/src/bundlemgr/bundle_mgr_proxy.cpp
推荐使用已定义的模板方法:
SendTransactCmd- 通用 IPC 请求发送方法(最常用)SendTransactCmdWithLogErrCode- 发送请求并记录错误码GetParcelableInfo- 获取单个 Parcelable 对象GetVectorFromParcelIntelligent- 获取对象向量
ErrCode BundleMgrProxy::GetCustomBundleInfo(const std::string &bundleName,
int32_t userId, CustomInfo &customInfo)
{
APP_LOGD("call GetCustomBundleInfo, bundleName: %{public}s, userId: %{public}d",
bundleName.c_str(), userId);
MessageParcel data;
// 1. 写入接口令牌
if (!data.WriteInterfaceToken(GetDescriptor())) {
APP_LOGE("fail to write interface token");
return ERR_APPEXECFWK_PARCEL_ERROR;
}
// 2. 写入参数
if (!data.WriteString(bundleName)) {
APP_LOGE("fail to write bundleName");
return ERR_APPEXECFWK_PARCEL_ERROR;
}
if (!data.WriteInt32(userId)) {
APP_LOGE("fail to write userId");
return ERR_APPEXECFWK_PARCEL_ERROR;
}
// 3. 使用 GetParcelableInfoWithErrCode 发送请求并获取结果
return GetParcelableInfoWithErrCode<CustomInfo>(
BundleMgrInterfaceCode::GET_CUSTOM_BUNDLE_INFO, data, customInfo);
}
第五步:实现 Host
5.1 在 bundle_mgr_host.h 中添加 Handle 方法声明(如需要)
文件: interfaces/inner_api/appexecfwk_core/include/bundlemgr/bundle_mgr_host.h
class BundleMgrHost : public IRemoteStub<IBundleMgr> {
private:
/**
* @brief Handles GetCustomBundleInfo function called from a IBundleMgr proxy object.
* @param data Indicates data to be read.
* @param reply Indicates reply to be sent;
* @return Returns ERR_OK if called successfully; returns error code otherwise.
*/
ErrCode HandleGetCustomBundleInfo(MessageParcel &data, MessageParcel &reply);
};
5.2 在 bundle_mgr_host.cpp 中实现 Handle 方法
文件: interfaces/inner_api/appexecfwk_core/src/bundlemgr/bundle_mgr_host.cpp
实现 Handle 方法来处理 IPC 请求,在该方法中完成 data 读取、调用业务逻辑、reply 写入:
ErrCode BundleMgrHost::HandleGetCustomBundleInfo(MessageParcel &data, MessageParcel &reply)
{
// 1. 从 data 中读取参数
std::string bundleName = Str16ToStr8(data.ReadString16());
int32_t userId = data.ReadInt32();
// 2. 调用业务逻辑方法
CustomInfo customInfo;
ErrCode result = GetCustomBundleInfo(bundleName, userId, customInfo);
// 3. 将返回值和输出参数写入 reply
if (!reply.WriteInt32(result)) {
APP_LOGE("write failed");
return ERR_APPEXECFWK_PARCEL_ERROR;
}
if (result == ERR_OK) {
if (!reply.WriteParcelable(&customInfo)) {
APP_LOGE("write failed");
return ERR_APPEXECFWK_PARCEL_ERROR;
}
}
return ERR_OK;
}
5.3 在 bundle_mgr_host.cpp 的 OnRemoteRequest 中添加 case 处理
文件: interfaces/inner_api/appexecfwk_core/src/bundlemgr/bundle_mgr_host.cpp
int BundleMgrHost::OnRemoteRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
BundleMemoryGuard memoryGuard;
APP_LOGD("bundle mgr host received message, code: %{public}u", code);
// 验证接口描述符
std::u16string descriptor = BundleMgrHost::GetDescriptor();
std::u16string remoteDescriptor = data.ReadInterfaceToken();
if (descriptor != remoteDescriptor) {
APP_LOGE("descriptor verification failed");
return OBJECT_NULL;
}
ErrCode errCode = ERR_OK;
switch (code) {
// ... 现有 case
// 新增 case 处理
case static_cast<uint32_t>(BundleMgrInterfaceCode::GET_CUSTOM_BUNDLE_INFO): {
errCode = HandleGetCustomBundleInfo(data, reply);
break;
}
// ... 其他 case
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
return errCode;
}
5.4 在 bundle_mgr_host_impl.h 中添加方法声明
文件: services/bundlemgr/include/bundle_mgr_host_impl.h
class BundleMgrHostImpl : public BundleMgrHost {
public:
// ... 现有方法声明
// 新增方法声明
ErrCode GetCustomBundleInfo(const std::string &bundleName,
int32_t userId, CustomInfo &customInfo) override;
};
5.5 在 bundle_mgr_host_impl.cpp 中实现业务逻辑
文件: services/bundlemgr/src/bundle_mgr_host_impl.cpp
ErrCode BundleMgrHostImpl::GetCustomBundleInfo(const std::string &bundleName,
int32_t userId, CustomInfo &customInfo)
{
APP_LOGI("GetCustomBundleInfo called, bundleName: %{public}s, userId: %{public}d",
bundleName.c_str(), userId);
// 1. 权限检查(可选)
if (!VerifyCallingPermission("ohos.permission.GET_BUNDLE_INFO")) {
APP_LOGE("permission verification failed");
return ERR_APPEXECFWK_PERMISSION_DENIED;
}
// 2. 参数验证
if (bundleName.empty()) {
APP_LOGE("bundleName is empty");
return ERR_APPEXECFWK_INVALID_PARAM;
}
if (userId < 0) {
APP_LOGE("invalid userId: %{public}d", userId);
return ERR_APPEXECFWK_INVALID_PARAM;
}
// 3. 业务逻辑实现 - 由用户根据实际需求实现
// TODO: 在此处实现具体的业务逻辑
// 示例:查询数据库、调用其他服务、计算结果等
return ERR_OK;
}
参考示例
参考 bundle_mgr_interface.h 中的现有方法:
GetBundleInfo- 获取 Bundle 信息GetApplicationInfo- 获取应用信息GetJsonProfile- 查询配置文件信息
这些方法的完整实现分布在以下文件中:
bundle_mgr_interface.h- 接口定义bundle_mgr_proxy.h/cpp- Proxy 实现bundle_mgr_host.cpp- Host case 处理bundle_mgr_host_impl.cpp- 业务逻辑实现