IDL (Interface Definition Language) 完整知识库
文档版本: v1.0 更新时间: 2026-02-11 源码版本: OpenHarmony ace_engine (master 分支)
📚 目录
概述
系统定位
IDL (Interface Definition Language) 是 OpenHarmony 框架中的跨进程接口定义语言,用于定义进程间通信(IPC)的接口规范。IDL 编译器能够根据 IDL 定义自动生成 Proxy(客户端)和 Stub(服务端)代码,实现高效的类型安全 IPC 通信。
技术架构
┌─────────────────────────────────────────────────────────────┐
│ IDL 文件定义 (.idl) │
│ - 接口声明 (interface) │
│ - 方法签名 (method) │
│ - 数据类型 (sequenceable, parcelable) │
│ - 权限声明 ([oneway]) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ IDL 编译器 │
│ - 语法解析 │
│ - 代码生成 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 生成的 C++ 代码 │
│ ├── Proxy 类 (客户端) │
│ ├── Stub 类 (服务端) │
│ ├── 类型转换代码 │
│ └── 序列化代码 │
└─────────────────────────────────────────────────────────────┘
核心价值
| 功能 | 描述 |
|---|---|
| 类型安全 | IDL 编译时检查类型,避免运行时错误 |
| 代码复用 | Proxy/Stub 自动生成,减少手动编写 IPC 代码 |
| 跨语言 | IDL 支持多种语言的绑定生成 |
| ABI稳定 | 接口版本化,保持向后兼容 |
| 自动序列化 | 自动生成数据序列化/反序列化代码 |
技术架构
IDL 编译和代码生成流程
┌─────────────────────────────────────────────────────────────┐
① IDL 接口定义 │
│ │
│ interface IUIServiceNew { │
│ [oneway] void RegisterCallBack(...); │
│ [oneway] void Push(...); │
│ } │
│ 源码:interfaces/inner_api/ui_service_manager/ │
│ IUIServiceMgrNew.idl │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
② IDL 编译器 (idlc) │
│ │
│ - 解析 .idl 文件 │
│ - 生成 Proxy 头文件 │
│ - 生成 Stub 头文件 │
│ - 生成序列化代码 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
③ 生成的代码文件 │
│ │
│ 接口/inner_api/ui_service_manager/include/ │
│ ├── ui_service_mgr_proxy.h (Proxy类) │
│ ├── ui_service_mgr_stub.h (Stub基类) │
│ └── ui_service_interface.h (接口声明) │
│ │
│ adapter/ohos/services/uiservice/src/ │
│ ├── ui_service_mgr_proxy.cpp (Proxy实现) │
│ ├── ui_service_mgr_stub.cpp (Stub实现) │
│ └── ui_mgr_service_idl.cpp (服务实现) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
④ 运行时 IPC 通信 │
│ │
│ App进程 → Proxy → Binder → Stub → Service进程 │
│ │
│ 源码:adapter/ohos/services/uiservice/ │
└─────────────────────────────────────────────────────────────┘
Proxy-Stub 架构
┌─────────────────────────────────────────────────────────────┐
│ Client Process (应用) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ UIServiceMgrProxy (客户端代理) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ MessageParcel (数据打包) │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ │ │
│ │ RegisterCallBack(want, uiService) │ │
│ │ Push(want, name, jsonPath, data, extraData) │ │
│ │ Request(want, name, data) │ │
│ │ │ │
│ └─────────────────────────────────────┘ │ │
│ ──────────────Binder IPC────────────────────┼────┬─────┘ │
│ │ │ │
│ ↓ │ ↓
┌───────────────────────────────────────────────────────────────────┐ │
│ Service Process (ACE Engine服务) │ │
│ │ │
│ ┌─────────────────────────────────────────────────┐ │ │
│ │ UIMgrServiceIdl (服务实现) │ │ │
│ │ │ │ │
│ │ ┌─────────────────────────────────────┐ │ │ │
│ │ │ MessageParcel (数据解包) │ │ │ │
│ │ └─────────────────────────────────────┘ │ │ │
│ │ │ │ │
│ │ OnPushCallBack(want, name, ...) │ │ │
│ │ OnRequestCallBack(want, name, ...) │ │ │
│ │ ReturnRequest(...) │ │ │
│ │ │ │ │
│ └─────────────────────────────────────┘ │ │ │
└───────────────────────────────────────────────────────────────────┘ │
↓ │
uiService 回调调用 │
│
应用层
目录结构
interfaces/inner_api/ui_service_manager/
├── IUIServiceMgrNew.idl # 服务管理器IDL定义
│ interface OHOS.Ace.IUIServiceMgrNew # 主接口
│ sequenceable Want..OHOS.AAFwk.Want # Want类型
│ sequenceable UiServiceStatisticEvent..OHOS.Ace.StatisticEventInfoParcel
│ sequenceable UiServiceStatisticEvent..OHOS.Ace.AppInfoParcel
│
├── include/
│ ├── ui_service_interface.h # 接口声明
│ ├── ui_service_mgr_proxy.h # Proxy类声明
│ ├── ui_service_mgr_stub.h # Stub类声明
│ ├── ui_service_mgr_client_idl.h # 客户端IDL辅助
│ ├── ui_service_mgr_xcollie.h # XCollie统计
│ └── ui_service_statistic_event.h # 统计事件定义
│
└── (Proxy/Stub实现代码在adapter/ohos/services/uiservice/src/)
adapter/ohos/services/uiservice/
├── include/
│ ├── ui_mgr_service_idl.h # 服务实现头文件
│ └── ui_service_hilog.h # 日志定义
│
├── src/
│ ├── ui_mgr_service_idl.cpp # 服务实现
│ ├── ui_service_mgr_proxy.cpp # Proxy实现
│ ├── ui_service_mgr_stub.cpp # Stub实现
│ ├── ui_service_mgr_client_idl.cpp # 客户端辅助
│ ├── ui_service_mgr_xcollie.cpp # 统计实现
│ └── ...
│
├── BUILD.gn # GN构建配置
├── uiservicems.gni # IDL编译配置
├── ui_service.cfg # 服务配置
└── uiservice.parcel # HAP配置
interfaces/inner_api/ui_service_manager/
├── IUIServiceNew.idl # 服务接口IDL
└── include/
├── ui_service_interface.h # IUIService接口
├── ui_service_mgr_interface.h # IUIServiceMgrNew接口
├── ui_service_mgr_proxy.h # Proxy头文件
├── ui_service_mgr_client_idl.h # 客户端IDL
└── ui_service_mgr_errors.h # 错误码定义
test/unittest/core/manager/drag_drop/
└── drag_drop_initiating_state_idle_test_ng.cpp # IDL服务测试
IDL 语言规范
基本语法
1. 接口声明
// 接口声明格式
[package] interface <InterfaceName> {
// 方法声明
};
// 实例:IUIServiceMgrNew.idl
package ohos.ace
interface OHOS.Ace.IUIServiceMgrNew {
// 方法...
};
2. 方法声明
// 方法格式
[oneway] void MethodName([in] Type paramName, ...);
// 关键字说明:
// - [oneway] : 单向调用,不等待响应
// - [in] : 输入参数
// 示例
[oneway] void RegisterCallBack([in] Want want, [in] IUIServiceNew uiService);
[oneway] void Push([in] Want want, [in] String name, [in] String jsonPath,
[in] String dataStr, [in] String extraData);
[oneway] void Request([in] Want want, [in] String name, [in] String dataStr);
3. 数据类型声明
sequenceable(序列化类型)
// sequenceable 用于定义可序列化的结构体
sequenceable <TypeName> {
// 字段声明
};
// 示例:AppInfoParcel
sequenceable AppInfoParcel {
String bundleName;
String abilityName;
String instanceKey;
String accessToken;
};
Parcelable(可打包类型)
// parcelable 用于定义简单的可打包类型
parcelable TypeDefinition;
// 示例:基本类型
parcelable String;
parcelable int32;
源码位置: interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl:16-19
sequenceable want..OHOS.AAFwk.Want;
interface OHOS.Ace.IUIServiceNew;
sequenceable UiServiceStatisticEvent..OHOS.Ace.StatisticEventInfoParcel;
sequenceable UiServiceStatisticEvent..OHOS.Ace.AppInfoParcel;
数据类型映射
| IDL 类型 | C++ 类型 | 说明 |
|---|---|---|
String |
std::string |
字符串 |
int32 |
int32_t |
32位整数 |
int64 |
int64_t |
64位整数 |
boolean |
bool |
布尔值 |
sequenceable |
生成的序列化类 | 可序列化结构体 |
parcelable |
基本类型 | 内置可打包类型 |
interface |
生成的接口类 | 接口类型 |
List<Type> |
std::vector<Type> |
列表类型 |
IPC 通信机制
MessageParcel 数据序列化
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_proxy.cpp
// Proxy端:数据打包
int32_t UIServiceMgrProxy::RegisterCallBack(const AAFwk::Want& want,
const sptr<IUIService>& uiService)
{
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_ASYNC);
// 1. 写入接口Token(用于接口验证)
if (!WriteInterfaceToken(data)) {
return UI_SERVICE_PROXY_INNER_ERR;
}
// 2. 序列化 Want 对象
if (!data.WriteParcelable(&want)) {
return ERR_INVALID_VALUE;
}
// 3. 序列化 RemoteObject(IUIServiceNew)
if (!data.WriteRemoteObject(uiService->AsObject())) {
return ERR_INVALID_VALUE;
}
// 4. 发送IPC请求
int32_t error = Remote()->SendRequest(
IUIServiceMgr::REGISTER_CALLBACK, data, reply, option);
if (error != NO_ERROR) {
LOGW("register callback fail, error: %d", error);
return error;
}
// 5. 读取返回结果
return reply.ReadInt32();
}
Stub 端请求分发
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_stub.cpp
// Stub端:请求分发
int32_t UIServiceMgrStub::OnRemoteRequest(uint32_t code,
MessageParcel& data,
MessageParcel& reply,
MessageOption& option)
{
// 1. 读取接口Token并验证
std::u16string descriptor = UIServiceMgrStub::GetDescriptor();
std::u16string remoteDescriptor = data.ReadInterfaceToken();
if (descriptor != remoteDescriptor) {
return ERR_INVALID_STATE; // 接口不匹配
}
// 2. 根据请求码分发到对应的处理函数
auto itFunc = requestFuncMap_.find(code);
if (itFunc != requestFuncMap_.end()) {
auto requestFunc = itFunc->second;
if (requestFunc != nullptr) {
return (this->*requestFunc)(data, reply);
}
}
// 3. 默认调用父类处理
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
// 请求函数映射表(在构造函数中初始化)
UIServiceMgrStub::UIServiceMgrStub() {
requestFuncMap_[REGISTER_CALLBACK] = &UIServiceMgrStub::RegisterCallBackInner;
requestFuncMap_[UNREGISTER_CALLBACK] = &UIServiceMgrStub::UnregisterCallBackInner;
requestFuncMap_[PUSH] = &UIServiceMgrStub::PushInner;
requestFuncMap_[REQUEST] = &UIServiceMgrStub::RequestInner;
requestFuncMap_[RETURN_REQUEST] = &UIServiceMgrStub::ReturnRequestInner;
}
服务端方法实现
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp
// 服务端实现:业务逻辑处理
int32_t UIServiceMgrStub::RegisterCallBackInner(MessageParcel& data,
MessageParcel& reply)
{
// 1. 权限检查:只有系统应用可以注册回调
UIServiceMgrXCollie uiServiceMgrXCollie(
"UISERVICE_REGISTER_CALLBACK", UI_MGR_SERVICE_TIMEOUT);
if (!IsSystemApp()) {
return ERR_PERMISSION_DENIED;
}
// 2. 反序列化 Want 对象
std::shared_ptr<AAFwk::Want> want(data.ReadParcelable<AAFwk::Want>());
if (want == nullptr) {
return ERR_INVALID_VALUE;
}
// 3. 反序列化 RemoteObject(IUIServiceNew)
auto object = data.ReadRemoteObject();
if (object == nullptr) {
return ERR_INVALID_VALUE;
}
auto uiService = iface_cast<IUIServiceNew>(object);
// 4. 调用业务层处理
int32_t result = RegisterCallBack(*want, uiService);
// 5. 写入返回结果
reply.WriteInt32(result);
return NO_ERROR;
}
服务架构
服务生命周期
源码位置: adapter/ohos/services/uiservice/include/ui_mgr_service_idl.h
class UIMgrServiceIdl : public SystemAbility,
public UIServiceMgrNewStub,
public std::enable_shared_from_this<UIMgrServiceIdl>
{
DECLARE_DELAYED_SINGLETON(UIMgrServiceIdl)
DECLARE_SYSTEM_ABILITY(UIMgrService)
public:
// 1. 服务启动
void OnStart() override;
// 2. 服务停止
void OnStop() override;
// 3. 查询服务状态
UIServiceRunningState QueryServiceState() const;
// 4. IDL 接口实现
int32_t RegisterCallBack(...) override;
int32_t UnregisterCallBack(...) override;
int32_t Push(...) override;
int32_t Request(...) override;
int32_t ReturnRequest(...) override;
int32_t Dump(...) override;
int32_t ReportStatisticEvents(...) override;
// 5. 远程请求处理(来自其他进程)
int32_t OnRemoteRequest(uint32_t code, MessageParcel& data,
MessageParcel& reply, MessageOption& option) override;
private:
// 辅助函数
const char* IpcCodeToString(uint32_t code);
bool IsSystemApp();
bool Init();
int32_t HandleRegister(...);
int32_t HandleUnregister(...);
// 事件循环和处理器
std::shared_ptr<EventRunner> eventLoop_;
std::shared_ptr<EventHandler> handler_;
UIServiceRunningState state_;
// 回调注册表
std::map<std::string, sptr<IUIServiceNew>> callbackMap_;
std::recursive_mutex uiMutex_;
};
服务启动流程
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp:38-83
void UIMgrServiceIdl::OnStart()
{
// 1. 检查是否已经运行
if (state_ == UIServiceRunningState::STATE_RUNNING) {
return;
}
// 2. 初始化服务
if (!Init()) {
return;
}
// 3. 设置状态为运行中
state_ = UIServiceRunningState::STATE_RUNNING;
// 4. 启动事件循环
eventLoop_->Run();
// 5. 发布服务(SA)
bool ret = Publish(DelayedSingleton<UIMgrServiceIdl>::GetInstance().get());
if (!ret) {
LOGW("Publish UIMgrServiceIdl failed");
return;
}
LOGI("Ace UI service OnStart");
}
初始化流程
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp:85-105
bool UIMgrServiceIdl::Init()
{
// 1. 创建事件循环器
eventLoop_ = AppExecFwk::EventRunner::Create("UIMgrServiceIdl");
if (eventLoop_ == nullptr) {
return false;
}
// 2. 创建事件处理器
handler_ = std::make_shared<AppExecFwk::EventHandler>(eventLoop_);
if (handler_ == nullptr) {
return false;
}
// 3. 初始化统计事件管理器
DelayedSingleton<StatisticEventManager>::GetInstance()->Init(handler_);
// 4. 添加看门狗线程监控
int32_t ret = HiviewDFX::Watchdog::GetInstance().AddThread(
"UIMgrServiceIdl", handler_, WATCHDOG_TIMEVAL);
if (ret != 0) {
LOGW("Add watchdog thread failed");
}
LOGI("Ace UI service init success");
return true;
}
编译生成
IDL 编译配置
源码位置: adapter/ohos/services/uiservice/uiservicems.gni
# IDL 编译配置
ui_service_manager_src_parcel = [
"interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl",
]
# 生成参数
idl_gen_include_dirs = [
"//foundation/arkui/ace_engine/interfaces/inner_api/ui_service_manager",
]
idl_out_dir = "$target_out_dir/ui_service_manager"
自动生成的代码结构
Proxy 头文件
生成位置: interfaces/inner_api/ui_service_manager/include/ui_service_mgr_proxy.h
// 自动生成的 Proxy 类
class UIServiceMgrProxy : public IRemoteBroker {
public:
explicit UIServiceMgrProxy(const sptr<IRemoteObject>& object);
// IDL 方法自动生成
int32_t RegisterCallBack(const AAFwk::Want& want, const sptr<IUIServiceNew>& uiService);
int32_t UnregisterCallBack(const AAFwk::Want& want);
int32_t Push(const AAFwk::Want& want, const std::string& name, ...);
int32_t Request(const AAFwk::Want& want, const std::string& name, ...);
int32_t ReturnRequest(const AAFwk::Want& want, ...);
private:
static constexpr int32_t UI_SERVICE_PROXY_INNER_ERR = -1;
static inline sptr<IRemoteObject> AsObject();
bool WriteInterfaceToken(MessageParcel& data);
};
Stub 头文件
生成位置: interfaces/inner_api/ui_service_manager/include/ui_service_mgr_stub.h
// 自动生成的 Stub 基类
class UIServiceMgrStub : public IRemoteBroker {
public:
// 构造函数:初始化请求映射表
UIServiceMgrStub();
virtual ~UIServiceMgrStub();
// 请求处理函数(纯虚函数,由子类实现)
virtual int32_t RegisterCallBackInner(MessageParcel& data, MessageParcel& reply) = 0;
virtual int32_t UnregisterCallBackInner(MessageParcel& data, MessageParcel& reply) = 0;
virtual int32_t PushInner(MessageParcel& data, MessageParcel& reply) = 0;
virtual int32_t RequestInner(MessageParcel& data, MessageParcel& reply) = 0;
virtual int32_t ReturnRequestInner(MessageParcel& data, MessageParcel& reply) = 0;
// 远程请求处理
int32_t OnRemoteRequest(uint32_t code, MessageParcel& data,
MessageParcel& reply, MessageOption& option) override;
// 接口Token
static inline std::u16string GetDescriptor();
protected:
std::map<uint32_t, int32_t (UIServiceMgrStub::*)(MessageParcel&, MessageParcel&)> requestFuncMap_;
bool IsSystemApp();
};
完整 API 清单
IDL 接口方法
IUIServiceMgrNew 接口
源码位置: interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl:21-27
interface OHOS.Ace.IUIServiceMgrNew {
// 1. 注册UI服务回调
[oneway] void RegisterCallBack([in] Want want, [in] IUIServiceNew uiService);
// 2. 注销UI服务回调
[oneway] void UnregisterCallBack([in] Want want);
// 3. 推送数据到UI
[oneway] void Push([in] Want want, [in] String name,
[in] String jsonPath, [in] String dataStr, [in] String extraData);
// 4. 请求数据
[oneway] void Request([in] Want want, [in] String name, [in] String dataStr);
// 5. 返回数据
[oneway] void ReturnRequest([in] Want want, [in] String source,
[in] String dataStr, [in] String extraData);
// 6. 报告统计事件
[oneway] void ReportStatisticEvents([in] AppInfoParcel appInfo,
[in] List<StatisticEventInfoParcel> events);
}
IUIServiceNew 接口
源码位置: interfaces/inner_api/ui_service_manager/IUIServiceNew.idl:18-21
interface OHOS.Ace.IUIServiceNew {
// 1. Push回调
[oneway] void OnPushCallBack([in] Want want, [in] String name,
[in] String jsonPath, [in] String dataStr, [in] String extraData);
// 2. Request回调
[oneway] void OnRequestCallBack([in] Want want, [in] String name, [in] String dataStr);
// 3. ReturnRequest回调
[oneway] void OnReturnRequest([in] Want want, [in] String source,
[in] String dataStr, [in] String extraData);
}
数据类型定义
StatisticEventInfoParcel
源码位置: interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl:18
sequenceable UiServiceStatisticEvent..OHOS.Ace.StatisticEventInfoParcel {
// 统计事件信息
String eventName;
String pageUrl;
int32 timestamp;
}
AppInfoParcel
源码位置: interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl:19
sequenceable UiServiceStatisticEvent..OHOS.Ace.AppInfoParcel {
// 应用信息
String bundleName;
String abilityName;
String instanceKey;
String accessToken;
}
错误码定义
源码位置: interfaces/inner_api/ui_service_manager/include/ui_service_mgr_errors.h
enum class UI_SERVICE_ERRORS {
NO_ERROR = 0,
UI_SERVICE_IS_NULL = -1,
UI_SERVICE_HANDLER_IS_NULL = -2,
UI_SERVICE_POST_TASK_FAILED = -3,
NO_CALLBACK_FOR_KEY = -4,
UI_SERVICE_PROXY_INNER_ERR = -5,
ERR_INVALID_VALUE = -6,
ERR_INVALID_DATA = -7,
INVALID_DATA = -8,
ERR_PERMISSION_DENIED = -9,
UI_SERVICE_NO_ERROR = -10,
ERR_INVALID_STATE = -11,
UI_SERVICE_TIMEOUT = -12,
};
// 错误消息
#define ERR_NO_CALLBACK_MSG "No callback for key"
#define ERR_PERM_DENIED_MSG "Permission denied"
核心实现细节
MessageParcel 序列化机制
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_proxy.cpp
// MessageParcel 数据写入流程
bool UIServiceMgrProxy::WriteInterfaceToken(MessageParcel& data)
{
// 写入接口描述符(用于接口验证)
if (!data.WriteInterfaceToken(UIServiceMgrProxy::GetDescriptor())) {
return false;
}
return true;
}
// 序列化 Want 对象
bool MessageParcel::WriteParcelable(const AAFwk::Want* want)
{
if (!want) {
return false;
}
// 序列化 Want 的各个字段
WriteParcelableElement(want->element_);
WriteParcelableElement(want->action_);
// ... 更多字段
return true;
}
// 序列化 RemoteObject
bool MessageParcel::WriteRemoteObject(const sptr<IRemoteObject>& object)
{
if (!object) {
return false;
}
// 写入对象指针(Binder机制)
data.WriteInterfaceToken(object->GetDescriptor());
data.WriteRawData(reinterpret_cast<const uint8_t*>(object.GetRefPtr()),
sizeof(object->GetRefPtr()));
return true;
}
反序列化机制
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_stub.cpp
// MessageParcel 数据读取流程
std::shared_ptr<AAFwk::Want> MessageParcel::ReadParcelable<AAFwk::Want>()
{
// 反序列化 Want 对象
auto want = std::make_shared<AAFwk::Want>();
// 读取各个字段
ReadParcelableElement(want->element_);
ReadParcelableElement(want->action_);
// ... 更多字段
return want;
}
// 读取 RemoteObject
sptr<IRemoteObject> MessageParcel::ReadRemoteObject()
{
// 读取对象指针
data.ReadInterfaceToken();
return iface_cast<IRemoteObject>(readRawData());
}
回调注册机制
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp:207-216
int32_t UIMgrServiceIdl::HandleRegister(const AAFwk::Want& want,
const sptr<IUIServiceNew>& uiService)
{
// 1. 生成回调Key
std::string keyStr = GetCallBackKeyStr(want);
std::lock_guard<std::recursive_mutex> lock(uiMutex_);
// 2. 检查是否已存在(如果存在则替换)
bool exist = CheckCallBackFromMap(keyStr);
if (exist) {
callbackMap_.erase(keyStr);
}
// 3. 存入回调Map
callbackMap_.emplace(keyStr, uiService);
return NO_ERROR;
}
// 生成回调Key
std::string UIMgrServiceIdl::GetCallBackKeyStr(const AAFwk::Want& want)
{
AppExecFwk::ElementName element = want.GetElement();
std::string bundleName = element.GetBundleName();
std::string keyStr = bundleName;
return keyStr;
}
回调调用机制
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp:153-169
int32_t UIMgrServiceIdl::Push(const AAFwk::Want& want,
const std::string& name,
const std::string& jsonPath,
const std::string& data,
const std::string& extraData)
{
// 1. 复制回调Map(避免锁定太久)
std::map<std::string, sptr<IUIServiceNew>> callbackMap;
{
std::lock_guard<std::recursive_mutex> lock(uiMutex_);
callbackMap = std::map<std::string, sptr<IUIServiceNew>>(callbackMap_);
}
// 2. 遍历所有注册的回调并调用
for (auto iter = callbackMap.begin(); iter != callbackMap.end(); ++iter) {
sptr<IUIServiceNew> uiService = iter->second;
if (uiService == nullptr) {
continue;
}
// 调用回调
uiService->OnPushCallBack(want, name, jsonPath, data, extraData);
}
return NO_ERROR;
}
权限验证机制
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_stub.cpp
bool UIServiceMgrStub::IsSystemApp()
{
// 1. 获取调用者的AccessToken ID
uint64_t accessTokenIDEx = IPCSkeleton::GetCallingFullTokenID();
// 2. 验证是否为系统应用
return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenIDEx);
}
// 在回调注册时使用
int32_t UIServiceMgrStub::RegisterCallBackInner(MessageParcel& data, MessageParcel& reply)
{
UIServiceMgrXCollie uiServiceMgrXCollie("UISERVICE_REGISTER_CALLBACK", UI_MGR_SERVICE_TIMEOUT);
// 只有系统应用可以注册回调
if (!IsSystemApp()) {
return ERR_PERMISSION_DENIED;
}
// ... 继续处理
}
使用示例
C++ 客户端调用 UI 服务
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_client_idl.cpp
// 1. 获取 UI 服务 Proxy
auto samgr = OHOS::SystemAbilityManagerClient::GetInstance()->GetSystemAbilityManager();
auto object = samgr->GetSystemAbility(UI_MGR_SERVICE_SA_ID);
auto uiServiceProxy = OHOS::Ace::UIServiceMgrProxy::AsInterface(object);
// 2. 准备 Want 对象
AAFwk::Want want;
want.SetElementName("UIService");
want.SetAction("action.register.callback");
// 3. 创建回调对象
class MyCallback : public OHOS::Ace::IUIServiceNew {
public:
void OnPushCallBack(const AAFwk::Want& want, const std::string& name,
const std::string& jsonPath, const std::string& dataStr,
const std::string& extraData) override {
LOGI("OnPushCallBack received: name=%s, data=%s", name.c_str(), dataStr.c_str());
// 处理回调
}
// ... 其他回调方法
};
auto myCallback = new MyCallback();
// 4. 注册回调
int32_t result = uiServiceProxy->RegisterCallBack(want, myCallback);
if (result == NO_ERROR) {
LOGI("Register callback success");
} else {
LOGE("Register callback failed: %d", result);
}
推送数据到 UI
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_client_idl.cpp
// 1. 获取 UI 服务 Proxy
auto uiServiceProxy = GetUIServiceProxy();
// 2. 准备数据
AAFwk::Want want;
want.SetElementName("MyApp");
want.SetAction("action.push.data");
// 3. 推送数据
std::string name = "myData";
std::string jsonPath = "";
std::string data = "Hello from C++";
std::string extraData = "";
int32_t result = uiServiceProxy->Push(want, name, jsonPath, data, extraData);
if (result == NO_ERROR) {
LOGI("Push data success");
} else {
LOGE("Push data failed: %d", result);
}
请求 UI 数据
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_client_idl.cpp
// 1. 获取 UI 服务 Proxy
auto uiServiceProxy = GetUIServiceProxy();
// 2. 准备 Want 对象
AAFwk::Want want;
want.SetElementName("MyApp");
want.SetAction("action.request.data");
// 3. 请求数据
std::string name = "requestData";
std::string data = "Please provide data";
int32_t result = uiServiceProxy->Request(want, name, data);
if (result == NO_ERROR) {
LOGI("Request data success");
} else {
LOGE("Request data failed: %d", result);
}
报告统计事件
源码位置: adapter/ohos/services/uiservice/src/ui_service_mgr_client_idl.cpp
// 1. 准备应用信息
AppInfoParcel appInfo;
appInfo.bundleName = "com.example.app";
appInfo.abilityName = "MainAbility";
appInfo.instanceKey = "instance_123";
appInfo.accessToken = "token_456";
// 2. 准备统计事件列表
std::vector<StatisticEventInfoParcel> events;
StatisticEventInfoParcel event1;
event1.eventName = "page_view";
event1.pageUrl = "/pages/index";
event1.timestamp = GetCurrentTimestamp();
events.push_back(event1);
// ... 添加更多事件
// 3. 报告统计事件
AAFwk::Want want;
want.SetElementName("MyApp");
want.SetAction("action.report.statistic");
int32_t result = uiServiceProxy->ReportStatisticEvents(appInfo, events);
if (result == NO_ERROR) {
LOGI("Report statistic events success");
} else {
LOGE("Report statistic events failed: %d", result);
}
调试指南
Dump 服务状态
源码位置: adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp:52-63
int32_t UIMgrServiceIdl::Dump(int32_t fd, const std::vector<std::u16string>& args)
{
std::lock_guard<std::recursive_mutex> lock(uiMutex_);
// 1. 输出总回调数
dprintf(fd, "total callbacks: %u\n", callbackMap_.size());
// 2. 输出所有回调key
if (!callbackMap_.empty()) {
dprintf(fd, "callback keys:\n");
}
for (const auto& callback : callbackMap_) {
dprintf(fd, " %s\n", callback.first.c_str());
}
return UI_SERVICE_NO_ERROR;
}
使用方法:
# 通过Hidumper工具dump服务信息
hidumper -s UIContentMgrService -a
# 通过Shell命令
service list | grep ui
dumpsys ui_service_manager
# 查看服务状态
hdc shell hidumper -s UIContentMgrService
启用 IDL 日志
// 在服务实现中添加详细日志
#include "ui_service_hilog.h"
#define TAG "UIMgrService"
void UIMgrServiceIdl::OnStart()
{
LOGI("OnStart called");
// ... 初始化逻辑
LOGI("EventLoop started with id=%d", eventLoop_->GetId());
}
IPC 调用追踪
// 追踪 IPC 请求
int32_t UIServiceMgrProxy::RegisterCallBack(...)
{
LOGD("RegisterCallBack called: bundleName=%s",
want.GetBundleName().c_str());
// IPC 调用
int32_t error = Remote()->SendRequest(...);
if (error != NO_ERROR) {
LOGE("RegisterCallBack failed: error=%d", error);
} else {
LOGI("RegisterCallBack success");
}
return error;
}
常见问题排查
| 问题 | 可能原因 | 检查方法 |
|---|---|---|
| 服务启动失败 | 权限不足、配置错误 | 检查服务配置、权限声明 |
| IPC 调用超时 | 服务未响应、死锁 | 检查服务状态、线程状态 |
| 回调未触发 | Key不匹配、应用未注册 | 检查Want参数、BundleName |
| 权限被拒绝 | 非系统应用、Token无效 | 检查AccessToken、应用签名 |
| 反序列化失败 | 数据格式错误、版本不匹配 | 检查IDL定义、数据格式 |
常见问题
IDL 相关问题
Q1: IDL 修改后需要重新编译吗?
A: 是的。IDL 文件修改后需要重新编译:
# 重新编译接口模块
./build.sh --product-name rk3568 --build-target ui_service_manager
# IDL 编译器会自动重新生成 Proxy/Stub 代码
Q2: 如何添加新的接口方法?
A: 1. 在 .idl 文件中添加方法声明:
[oneway] void NewMethod([in] String param1, [in] int32 param2);
- 在 Stub 实现中添加对应方法:
int32_t UIServiceMgrStub::NewMethodInner(MessageParcel& data, MessageParcel& reply) {
// 解析参数
std::string param1 = data.ReadString();
int32_t param2 = data.ReadInt32();
// 业务处理
int32_t result = HandleNewMethod(param1, param2);
// 写入结果
reply.WriteInt32(result);
return NO_ERROR;
}
Q3: sequenceable 和 parcelable 的区别?
A: - sequenceable: 定义复杂的可序列化结构体,生成对应的类
parcelable: 声明基本类型为可打包类型
// 复杂结构体
sequenceable MyData {
String name;
int32 value;
List<int32> items;
};
// 基本类型
parcelable String;
parcelable int32;
IPC 通信问题
Q4: 如何处理大额数据传输?
A: IDL 支持通过 MessageParcel 传输大数据:
// Proxy端:写入大数据
MessageParcel data;
data.WriteInterfaceToken(...);
data.WriteRawData(largeBuffer, bufferSize);
// Stub端:读取大数据
uint8_t* buffer = new uint8_t[bufferSize];
data.ReadRawData(buffer, bufferSize);
// 使用后及时释放
delete[] buffer;
Q5: oneway 方法有什么限制?
A: oneway 是单向调用,特点:
- 客户端不等待响应
- 服务端异步处理
- 不能传递返回值
- 适合通知类接口
// ✅ oneway - 适合通知
[oneway] void PushNotification(...);
// ❌ 普通方法 - 适合需要返回值
int32_t GetData(...) returns int32;
Q6: 如何确保 IPC 线程安全?
A: IDL 生成的 Proxy/Stub 代码是线程安全的:
- Proxy: 可以从任意线程调用
- Stub: 在 Binder 线程中处理请求
- 使用互斥锁保护共享数据
// Stub端使用互斥锁
int32_t UIServiceMgrStub::RegisterCallBackInner(...) {
// 自动在Binder线程中调用
// 使用 std::lock_guard 保护 callbackMap_
std::lock_guard<std::recursive_mutex> lock(uiMutex_);
// ... 处理逻辑
}
服务管理问题
Q7: 如何获取服务是否运行?
A: 通过 ServiceManager 查询:
auto samgr = SystemAbilityManagerClient::GetInstance()->GetSystemAbilityManager();
auto object = samgr->GetSystemAbility(UI_MGR_SERVICE_SA_ID);
auto uiServiceProxy = UIServiceMgrProxy::AsInterface(object);
// 查询服务状态(如果服务支持)
if (uiServiceProxy) {
// 调用服务方法查询状态
}
Q8: 多个应用可以注册回调吗?
A: 是的,但每个应用独立注册,使用不同的Key:
// App1 注册
want.SetElementName("App1");
uiServiceProxy->RegisterCallBack(want, callback1);
// App2 注册
want.SetElementName("App2");
uiServiceProxy->RegisterCallBack(want, callback2);
// 内部通过 BundleName 区分不同应用的回调
Q9: 如何处理服务重启?
A: 在 Proxy 端实现重连机制:
class UIServiceClient {
sptr<UIServiceMgrProxy> proxy_;
void Connect() {
// 1. 获取服务
proxy_ = GetUIServiceProxy();
// 2. 设置死亡通知
auto deathRecipient = new MyDeathRecipient(this);
proxy_->AsObject()->AddDeathRecipient(deathRecipient);
// 3. 重新注册回调
RegisterCallbacks();
}
void OnServiceDied() {
LOGW("Service died, reconnecting...");
proxy_ = nullptr;
// 延迟重连
std::this_thread::sleep_for(std::chrono::seconds(1));
Connect();
}
};
性能优化问题
Q10: 如何减少 IPC 调用开销?
A: 优化建议:
- 批量操作: 将多个操作合并为一次调用
- 使用 oneway: 不需要返回值的操作使用 oneway
- 减少数据拷贝: 使用移动语义
- 缓存 Proxy: 不要每次都重新获取
// ✅ 优化:批量操作
// ❌ 不优化:单独调用
Push("data1", "path1", "val1");
Push("data2", "path2", "val2");
// ✅ 优化:使用 oneway
[oneway] void Notify(...);
// ✅ 优化:缓存 Proxy
class MyClass {
sptr<UIServiceMgrProxy> proxy_;
void Init() {
proxy_ = GetUIServiceProxy(); // 获取一次
}
void SendData() {
proxy_->Push(...); // 重用
}
};
附录
参考源码路径
| 功能模块 | 源码路径 |
|---|---|
| IDL 定义 | interfaces/inner_api/ui_service_manager/IUIServiceMgrNew.idl |
| IDL 定义(服务接口) | interfaces/inner_api/ui_service_manager/IUIServiceNew.idl |
| Proxy 头文件 | interfaces/inner_api/ui_service_manager/include/ui_service_mgr_proxy.h |
| Stub 头文件 | interfaces/inner_api/ui_service_manager/include/ui_service_mgr_stub.h |
| 服务实现头 | adapter/ohos/services/uiservice/include/ui_mgr_service_idl.h |
| 服务实现 | adapter/ohos/services/uiservice/src/ui_mgr_service_idl.cpp |
| Proxy 实现 | adapter/ohos/services/uiservice/src/ui_service_mgr_proxy.cpp |
| Stub 实现 | adapter/ohos/services/uiservice/src/ui_service_mgr_stub.cpp |
| 错误码定义 | interfaces/inner_api/ui_service_manager/include/ui_service_mgr_errors.h |
| 统计事件定义 | interfaces/inner_api/ui_service_manager/include/ui_service_statistic_event.h |
| 服务配置 | adapter/ohos/services/uiservice/ui_service.cfg |
| IDL 编译配置 | adapter/ohos/services/uiservice/uiservicems.gni |
IPC 相关源码
| 功能 | 源码路径 |
|---|---|
| MessageParcel | frameworks/core/common/communication/message_parcel.h |
| IPC Skeleton | test/mock/ohos_mock/ipc_single/ipc_skeleton.h |
| Remote Broker | test/mock/ohos_mock/ipc_single/iremote_broker.h |
相关知识库
- Inner_API_Knowledge_Base.md - Inner API 完整知识库
- Gesture_Drag_Drop_Knowledge_Base_CN.md - 手势与拖拽系统
相关文档
- CLAUDE.md - 项目级指导文档
- 如何新增一个组件.md - 组件开发指南
OpenHarmony 文档
- OpenHarmony IDL 文档
- OpenHarmony IPC 指南
- OpenHarmony SystemAbility 开发指南
文档结束