2. HAL层基础:HIDL与AIDL接口定义、QTI HAL Service启动流程、binder与hwbinder通信模型

2.1 HIDL 与 AIDL 接口定义

在 QTI 平台中,HAL 层接口定义经历了从 HIDL 到 AIDL 的演进。HIDL(HAL Interface Definition Language)是 Android 8.0 引入的接口定义语言,专为 Treble 架构设计,用于实现 Framework 与 HAL 之间的稳定接口。AIDL(Android Interface Definition Language)则从 Android 12 开始被推荐用于新的 HAL 模块,统一了跨进程通信的接口定义方式。

特性 HIDL AIDL(HAL 场景)
引入版本 Android 8.0 (Treble) Android 12 (推荐)
接口文件后缀 .hal .aidl
后端支持 hwbinder + passthrough binder + hwbinder
包名规范 android.hardware.xxx@X.Y android.hardware.xxx.IXxx
服务注册 hwservicemanager servicemanager (统一)
稳定性 强(版本化接口) 强(支持冻结接口)
代码生成 hidl-gen aidl-cpp

2.1.1 HIDL 接口定义示例

以下是一个典型的 QTI 平台 HIDL 接口定义,用于控制摄像头传感器:

// types.hal
package android.hardware.camera.provider@3.5;

enum CameraDeviceStatus : int32_t {
    PRESENT = 0,
    ENUMERATING = 1,
    NOT_PRESENT = 2
};

struct CameraMetadata {
    vec<uint8_t> metadata;
    int32_t tagCount;
};
// ICameraProvider.hal
package android.hardware.camera.provider@3.5;

interface ICameraProvider {
    getCameraIdList() generates (vec<string> cameraIds);
    getCameraDeviceInterface_V3(
        string cameraId
    ) generates (ICameraDevice device, Status status);
    setCallback(ICameraProviderCallback callback);
};

2.1.2 AIDL 接口定义示例

Android 12 之后,QTI 平台开始使用 AIDL 定义 HAL 接口,统一了与系统服务的通信方式:

// IMySensor.aidl
package android.hardware.mysensor;

interface IMySensor {
    /**
     * 获取传感器数据
     * @param sensorId 传感器ID
     * @return 传感器数据数组
     */
    float[] readSensorData(int sensorId);

    /**
     * 注册传感器事件回调
     */
    void registerCallback(IMySensorCallback callback);

    /**
     * 配置传感器采样率
     * @param sensorId 传感器ID
     * @param rateHz 采样率(Hz)
     */
    void setSamplingRate(int sensorId, int rateHz);
}
迁移建议: 对于新开发的 QTI HAL 模块,优先使用 AIDL 定义接口。AIDL 支持更丰富的类型系统、默认方法实现和更简洁的代码生成流程。对于已有 HIDL 接口的模块,可通过兼容层逐步迁移。

2.2 QTI HAL Service 启动流程

QTI 平台的 HAL Service 启动流程遵循 Android Treble 架构规范,涉及 init 进程、hwservicemanager/servicemanager、HAL 守护进程等多个组件。以下流程图展示了典型的启动序列:

QTI HAL Service 启动流程 init 进程启动 解析 .rc 文件 启动 HAL 守护进程 初始化 HIDL/AIDL 接口 注册到 ServiceManager 等待客户端请求 关键点:HAL 守护进程通过 hwservicemanager(HIDL)或 servicemanager(AIDL)注册服务实例, 客户端通过服务名获取代理对象,建立跨进程通信通道。

2.2.1 启动流程关键步骤

  1. init 进程解析 .rc 文件: 系统启动时,init 进程读取 /vendor/etc/init/ 目录下的 HAL 服务 .rc 文件,例如 android.hardware.camera.provider@3.5-service.rc。
  2. 启动 HAL 守护进程: init 根据 .rc 文件中的 service 声明,fork 并执行对应的 HAL 可执行文件,例如 /vendor/bin/hw/android.hardware.camera.provider@3.5-service。
  3. 初始化接口: HAL 进程启动后,创建 HIDL/AIDL 接口实现对象,初始化硬件资源(如打开设备节点、分配共享内存)。
  4. 注册服务: 调用 hwservicemanager(HIDL)或 servicemanager(AIDL)的注册接口,将服务实例注册到全局服务列表中。
  5. 进入事件循环: HAL 进程进入主循环,等待客户端通过 binder/hwbinder 发送请求。
死锁风险点: 在 HAL 服务初始化阶段,如果存在跨服务依赖(如 Camera HAL 依赖 Sensor HAL),且双方在注册服务时互相等待对方完成初始化,极易形成死锁。Perfetto 分析中应重点关注 onInit 阶段的线程状态。

2.3 Binder 与 HwBinder 通信模型

QTI 平台中存在两套跨进程通信机制:Binder(用于 Framework 层)和 HwBinder(用于 HAL 层)。理解两者的差异对于死锁排查至关重要。

特性 Binder HwBinder
所属层 Framework / 系统服务 HAL 层(Treble)
驱动 /dev/binder /dev/hwbinder
服务管理器 servicemanager hwservicemanager
线程池 默认 16 线程 默认 4 线程
事务优先级 支持优先级继承 支持优先级继承
死锁常见场景 跨服务循环调用 HAL 线程池耗尽 + 同步回调

2.3.1 通信模型对比图

Binder vs HwBinder 通信模型 Binder 域(Framework) SystemServer App Process servicemanager binder 驱动 线程池:16 线程 优先级继承:支持 典型死锁:A→B→A 循环 HwBinder 域(HAL) Camera HAL Sensor HAL hwservicemanager hwbinder 驱动 线程池:4 线程 优先级继承:支持 典型死锁:线程池耗尽 + 同步回调 跨域调用 死锁排查要点:当 Framework 通过 Binder 调用 HAL 服务时,如果 HAL 内部又通过 HwBinder 同步回调 Framework 或其他 HAL 服务,且双方线程池均已耗尽,将形成跨域死锁。Perfetto 中可观察到线程状态为 "Uninterruptible Sleep (D)" 且堆栈指向 binder 驱动。

2.3.2 通信流程与死锁场景

正常通信流程:

  1. 客户端(如 SystemServer)通过 Binder 向 HAL 服务发送请求。
  2. HAL 服务从 HwBinder 线程池中分配一个线程处理请求。
  3. HAL 服务执行硬件操作,可能通过 HwBinder 调用其他 HAL 服务。
  4. 处理完成后,通过 Binder/HwBinder 返回结果给客户端。

典型死锁场景:

  • 线程池耗尽: HwBinder 线程池默认只有 4 个线程。如果 4 个线程都在等待同步回调,而回调需要新的线程处理,则所有线程阻塞,形成死锁。
  • 跨域循环依赖: Framework 通过 Binder 调用 HAL A,HAL A 通过 HwBinder 调用 HAL B,HAL B 又通过 Binder 回调 Framework 中的某个服务,形成 A→B→A 循环。
  • 服务注册死锁: 两个 HAL 服务在 onInit 阶段互相等待对方完成注册,导致双方均无法完成初始化。
排查建议: 在 Perfetto 分析中,重点关注以下信号:
1. HwBinder 线程池中所有线程处于 Binder: transaction 状态。
2. 线程堆栈显示在 ioctl 调用上等待。
3. 存在跨域(Binder ↔ HwBinder)的同步调用链。
4. 服务注册阶段出现超时或卡死。