e704e1e2创建于 2月11日历史提交

IDL (Interface Definition Language) 完整知识库

文档版本: v1.0 更新时间: 2026-02-11 源码版本: OpenHarmony ace_engine (master 分支)


📚 目录

  1. 概述
  2. 技术架构
  3. 目录结构
  4. IDL语言规范
  5. IPC通信机制
  6. 服务架构
  7. 编译生成
  8. 完整API清单
  9. 核心实现细节
  10. 使用示例
  11. 调试指南
  12. 常见问题

概述

系统定位

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);
  1. 在 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: 优化建议:

  1. 批量操作: 将多个操作合并为一次调用
  2. 使用 oneway: 不需要返回值的操作使用 oneway
  3. 减少数据拷贝: 使用移动语义
  4. 缓存 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

相关知识库

相关文档

OpenHarmony 文档

  • OpenHarmony IDL 文档
  • OpenHarmony IPC 指南
  • OpenHarmony SystemAbility 开发指南

文档结束