Installs 进程 IPC 接口方法添加步骤指南
本文档详细说明了在 Installs 进程中添加新 IPC 接口方法的完整流程。
Installs 进程架构
- 系统能力 ID: SA 511
- 接口类:
IInstalld - 接口描述符:
u"ohos.appexecfwk.Installd" - 用途: 特权文件操作、目录管理、底层操作
- 安全机制: 必须验证调用方是否为 foundation 进程
文件清单
需要修改的文件(共 8 个):
services/bundlemgr/include/ipc/installd_interface.h- 接口方法声明services/bundlemgr/include/bundle_framework_services_ipc_interface_code.h- 接口代码枚举services/bundlemgr/include/ipc/installd_proxy.h- Proxy 类定义services/bundlemgr/src/ipc/installd_proxy.cpp- Proxy 实现services/bundlemgr/include/ipc/installd_host.h- Host 类定义services/bundlemgr/src/ipc/installd_host.cpp- Host case 处理services/bundlemgr/include/installd/installd_host_impl.h- 业务实现类定义services/bundlemgr/src/installd/installd_host_impl.cpp- 业务逻辑实现(必须包含 foundation 进程检查)
完整实现步骤
第二步:添加接口方法声明
文件: services/bundlemgr/include/ipc/installd_interface.h
在 IInstalld 类中添加方法声明:
class IInstalld : public IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.Installd");
// ... 现有方法
/**
* @brief 清理特定目录
* @param targetDir 目标目录路径
* @param cleanOptions 清理选项
* @return 成功返回 ERR_OK,失败返回错误码
*/
virtual ErrCode CleanSpecificDir(const std::string &targetDir,
const CleanOptions &cleanOptions)
{
return ERR_OK;
}
};
注意: IInstalld 中的方法提供默认实现 return ERR_OK;
第三步:添加接口代码枚举
文件: services/bundlemgr/include/bundle_framework_services_ipc_interface_code.h
查看现有枚举值,使用下一个未使用的编号:
enum class InstalldInterfaceCode : uint32_t {
CREATE_BUNDLE_DIR = 1,
EXTRACT_MODULE_FILES = 2,
// ... 现有代码
CLEAR_DIR = 95,
RESTORECON_PATH = 96,
RESET_BMS_DB_SECURITY = 97,
COPY_DIR = 98,
DELETE_CERT_AND_REMOVE_KEY = 99,
CLEAN_SPECIFIC_DIR = 100, // 新增 - 使用下一个可用的编号
};
第四步:实现 Proxy
4.1 在 installd_proxy.h 中添加方法声明(如需要)
文件: services/bundlemgr/include/ipc/installd_proxy.h
class InstalldProxy : public IRemoteProxy<IInstalld> {
public:
explicit InstalldProxy(const sptr<IRemoteObject> &impl);
virtual ~InstalldProxy() override;
// ... 现有方法声明
// 新增方法
ErrCode CleanSpecificDir(const std::string &targetDir,
const CleanOptions &cleanOptions) override;
};
4.2 在 installd_proxy.cpp 中实现方法
文件: services/bundlemgr/src/ipc/installd_proxy.cpp
推荐使用已定义的模板方法:
TransactInstalldCmd- Installd IPC 请求发送方法
ErrCode InstalldProxy::CleanSpecificDir(const std::string &targetDir,
const CleanOptions &cleanOptions)
{
LOG_D(BMS_TAG_INSTALLD, "call CleanSpecificDir, targetDir: %{public}s", targetDir.c_str());
MessageParcel data;
INSTALLD_PARCEL_WRITE_INTERFACE_TOKEN(data, (GetDescriptor()));
INSTALLD_PARCEL_WRITE(data, String, targetDir);
// 写入复杂参数
if (!data.WriteRawData(&cleanOptions, sizeof(CleanOptions))) {
LOG_E(BMS_TAG_INSTALLD, "fail to write cleanOptions");
return ERR_APPEXECFWK_IPC_WRITE_PARCEL_ERROR;
}
MessageParcel reply;
MessageOption option;
return TransactInstalldCmd(InstalldInterfaceCode::CLEAN_SPECIFIC_DIR, data, reply, option);
}
TransactInstalldCmd 封装了以下操作:
- Remote() 对象检查
- SendRequest 调用
- 错误处理
- 返回值读取
第五步:实现 Host
5.1 在 installd_host.h 中添加 Handle 方法声明(如需要)
文件: services/bundlemgr/include/ipc/installd_host.h
class InstalldHost : public IRemoteStub<IInstalld> {
private:
/**
* @brief Handles CleanSpecificDir function called from a IInstalld proxy object.
* @param data Indicates data to be read.
* @param reply Indicates reply to be sent;
* @return Returns true if called successfully; returns false otherwise.
*/
bool HandleCleanSpecificDir(MessageParcel &data, MessageParcel &reply);
};
5.2 在 installd_host.cpp 中实现 Handle 方法
文件: services/bundlemgr/src/ipc/installd_host.cpp
实现 Handle 方法来处理 IPC 请求,在该方法中完成 data 读取、调用业务逻辑、reply 写入:
bool InstalldHost::HandleCleanSpecificDir(MessageParcel &data, MessageParcel &reply)
{
// 1. 从 data 中读取参数
std::string targetDir = Str16ToStr8(data.ReadString16());
CleanOptions cleanOptions;
const char* dataPtr = reinterpret_cast<const char*>(data.ReadRawData(sizeof(CleanOptions)));
if (dataPtr == nullptr) {
LOG_E(BMS_TAG_INSTALLD, "fail to read cleanOptions");
reply.WriteInt32(ERR_APPEXECFWK_IPC_READ_PARCEL_ERROR);
return false;
}
cleanOptions = *reinterpret_cast<const CleanOptions*>(dataPtr);
// 2. 调用业务逻辑方法
ErrCode result = CleanSpecificDir(targetDir, cleanOptions);
// 3. 将返回值写入 reply
if (!reply.WriteInt32(result)) {
LOG_E(BMS_TAG_INSTALLD, "fail to write result");
return false;
}
return true;
}
5.3 在 installd_host.cpp 的 OnRemoteRequest 中添加 case
文件: services/bundlemgr/src/ipc/installd_host.cpp
int InstalldHost::OnRemoteRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
std::u16string descriptor = InstalldHost::GetDescriptor();
std::u16string remoteDescriptor = data.ReadInterfaceToken();
if (descriptor != remoteDescriptor) {
LOG_E(BMS_TAG_INSTALLD, "InstalldHost::OnRemoteRequest descriptor verification failed");
return OBJECT_NULL;
}
bool ret = false;
switch (code) {
// ... 现有 case
// 新增 case 处理
case static_cast<uint32_t>(InstalldInterfaceCode::CLEAN_SPECIFIC_DIR): {
ret = HandleCleanSpecificDir(data, reply);
break;
}
// ... 其他 case
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
return ret ? NO_ERROR : ERR_NULL;
}
5.4 在 installd_host_impl.h 中添加方法声明
文件: services/bundlemgr/include/installd/installd_host_impl.h
class InstalldHostImpl : public InstalldHost {
public:
// ... 现有方法声明
// 新增方法声明
ErrCode CleanSpecificDir(const std::string &targetDir,
const CleanOptions &cleanOptions) override;
};
5.5 在 installd_host_impl.cpp 中实现业务逻辑
文件: services/bundlemgr/src/installd/installd_host_impl.cpp
ErrCode InstalldHostImpl::CleanSpecificDir(const std::string &targetDir,
const CleanOptions &cleanOptions)
{
// 1. 检查调用方是否为 foundation 进程(必须)
if (!InstalldPermissionMgr::VerifyCallingPermission(Constants::FOUNDATION_UID)) {
LOG_E(BMS_TAG_INSTALLD, "installd permission denied, only used for foundation process");
return ERR_APPEXECFWK_INSTALLD_PERMISSION_DENIED;
}
// 2. 参数验证
if (targetDir.empty()) {
LOG_E(BMS_TAG_INSTALLD, "targetDir is empty");
return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
}
// 3. 业务逻辑实现 - 由用户根据实际需求实现
// TODO: 在此处实现具体的业务逻辑
// 示例:文件/目录操作、调用系统服务等
return ERR_OK;
}
重要: Installs 进程的所有方法都必须首先检查调用方是否为 foundation 进程:
if (!InstalldPermissionMgr::VerifyCallingPermission(Constants::FOUNDATION_UID)) {
LOG_E(BMS_TAG_INSTALLD, "installd permission denied, only used for foundation process");
return ERR_APPEXECFWK_INSTALLD_PERMISSION_DENIED;
}
参考示例
参考 installd_interface.h 中的现有方法:
CreateBundleDir- 创建 Bundle 目录ExtractFiles- 提取文件RemoveBundleDataDir- 删除 Bundle 数据目录SetDirApl- 设置目录 APL
这些方法的完整实现分布在以下文件中:
installd_interface.h- 接口定义installd_proxy.h/cpp- Proxy 实现installd_host.cpp- Host case 处理installd_host_impl.cpp- 业务逻辑实现