4. HAL 接口定义:.hal 文件的语法结构

HAL(Hardware Abstraction Layer)接口定义文件以 .hal 为扩展名,是 VTS 测试框架验证 HAL 层协议一致性的核心依据。本章系统讲解 .hal 文件的语法结构、包声明、接口定义、方法签名及数据类型,帮助测试工程师准确理解接口规范,为编写 VTS 测试用例奠定基础。

学习目标:掌握 .hal 文件的标准语法,能够独立解析和编写 HAL 接口定义,理解数据类型在跨进程通信中的序列化规则。

4.1 .hal 文件整体语法结构

.hal 文件采用类 C++ 的语法风格,但具有严格的层次结构。一个完整的 .hal 文件由 package 声明、import 导入、类型定义和接口定义四部分组成。

// 示例:ILight.hal
package android.hardware.light@2.0;

import android.hardware.graphics.common@1.0::types;

enum FlashMode : int32_t {
    NONE,
    TORCH,
    FLASH
};

struct LightState {
    FlashMode flashMode;
    uint8_t brightness;
    uint32_t color;
};

interface ILight {
    setLight(LightState state) generates (bool success);
    getLight() generates (LightState state);
};
语法要点:
  • 文件扩展名固定为 .hal,每个文件通常定义一个接口或一组相关类型。
  • 注释支持 // 单行和 /* */ 多行两种风格。
  • 语句以分号 ; 结束,块定义使用花括号 {}。
  • 标识符区分大小写,遵循驼峰命名规范。
.hal 文件语法结构 .hal 文件语法结构 .hal 文件 package 声明 import 导入 类型定义 interface 定义 struct enum union 方法签名 语法结构说明 • package 声明:定义接口所属的包名和版本号,如 android.hardware.light@2.0 • import 导入:引用其他包中的类型定义,避免重复声明 • 类型定义:在接口外定义 struct/enum/union 等复合数据类型 • interface 定义:声明 HAL 接口及其方法签名,是 VTS 测试的核心验证对象

4.2 package 声明

package 声明定义了 HAL 接口的命名空间和版本号,是 .hal 文件的第一条有效语句。其语法格式如下:

package <vendor>.<subsystem>.<module>@<major>.<minor>;
组成部分 说明 示例
vendor 厂商或组织名称,通常为 android.hardware android.hardware
subsystem 子系统分类,如 camera、sensors、graphics camera
module 具体模块名称,如 device、provider device
major.minor 主版本号和次版本号,用于接口兼容性管理 @3.4
版本兼容性规则:主版本号不同表示接口不兼容,VTS 测试会严格校验;次版本号不同表示向后兼容,新增方法不会导致旧测试失败。

常见 package 声明示例:

package android.hardware.camera.device@3.4;
package android.hardware.sensors@1.0;
package android.hardware.graphics.composer@2.1;
package vendor.google.example@1.0;  // 厂商自定义接口

4.3 interface 定义

interface 是 HAL 接口的核心,定义了一组可供客户端调用的方法。每个 interface 可以包含多个方法签名,并支持继承机制。

interface IMyInterface {
    // 同步方法:调用后等待返回结果
    doSomething(int32_t input) generates (int32_t output);
    
    // 单向方法:不等待返回,无返回值
    oneway fireAndForget(uint32_t event);
    
    // 回调方法:服务端主动向客户端推送数据
    registerCallback(ICallback callback);
};

4.3.1 接口命名规范

规范项 要求 正确示例 错误示例
前缀 必须以 I 开头 ICameraDevice CameraDevice
命名风格 大驼峰命名法 ISensorManager Isensor_manager
文件对应 接口名与文件名一致 ILight.hal LightInterface.hal

4.3.2 接口继承

HAL 接口支持单继承,子接口继承父接口的所有方法:

interface IBase {
    baseMethod() generates (int32_t result);
};

interface IDerived : IBase {
    derivedMethod() generates (int32_t result);
};
HAL 接口继承关系 HAL 接口继承关系 IBase(父接口) baseMethod() → int32_t IDerived(子接口) derivedMethod() → int32_t IOtherDerived(子接口) otherMethod() → void 子接口继承父接口的所有方法,并可添加新的方法。VTS 测试需验证继承链的完整性。

4.4 方法签名

方法签名定义了 HAL 接口中可调用的操作,包括方法名、输入参数和输出参数。HAL 的方法签名支持多种模式,以适应不同的通信场景。

4.4.1 方法签名语法

[oneway] <returnType> <methodName>(<inputParams>) [generates (<outputParams>)];
语法元素 是否必需 说明
oneway 可选 标记为单向调用,不等待服务端处理完成,无返回值
returnType 必需 返回值类型,可以是基本类型或复合类型
methodName 必需 方法名,小驼峰命名
inputParams 可选 输入参数列表,多个参数用逗号分隔
generates 可选 定义输出参数,用于返回多个值或回调结果

4.4.2 方法签名模式

HAL 接口支持三种方法调用模式,每种模式对应不同的 VTS 测试策略:

  • 同步模式(默认):客户端发送请求后阻塞等待服务端返回结果,适用于需要立即获取结果的场景。
  • 单向模式(oneway):客户端发送请求后立即返回,不等待服务端处理,适用于日志、事件通知等场景。
  • 生成模式(generates):允许方法返回多个输出参数,适用于需要同时返回状态和数据的场景。
// 同步模式:设置亮度,等待返回成功状态
setBrightness(uint8_t level) generates (bool success);

// 单向模式:发送事件通知,不等待返回
oneway notifyEvent(uint32_t eventId);

// 生成模式:获取传感器数据,返回多个值
getSensorData() generates (int32_t x, int32_t y, int32_t z, int64_t timestamp);
VTS 测试要点:
  • 同步方法需要验证超时处理机制,默认超时时间为 5 秒。
  • 单向方法无法通过返回值判断执行结果,需通过回调或状态查询验证。
  • generates 中的输出参数顺序必须与实现一致,VTS 会严格校验参数类型和顺序。

4.5 数据类型:struct / enum / union

.hal 文件支持三种复合数据类型:struct(结构体)、enum(枚举)和 union(联合体)。这些类型在 HAL 接口中用于定义复杂的数据结构,VTS 测试需要验证其序列化和反序列化的正确性。

4.5.1 struct(结构体)

struct 用于组合多个字段形成复合数据结构,是 HAL 接口中最常用的数据类型。

struct CameraMetadata {
    int32_t sensorWidth;
    int32_t sensorHeight;
    float focalLength;
    vec<uint8_t> rawData;  // 变长数组
    bool isAvailable;
};
字段类型 说明 示例
基本类型 int32_t、uint8_t、float、bool 等 int32_t id;
字符串 使用 string 类型 string name;
数组 使用 vec<T> 表示变长数组 vec<uint8_t> data;
嵌套结构 struct 内部可包含其他 struct CameraMetadata meta;
枚举 可包含 enum 类型字段 FlashMode mode;

4.5.2 enum(枚举)

enum 定义一组命名的整型常量,用于表示有限的状态集合。HAL 中的 enum 必须显式指定底层类型。

enum CameraError : int32_t {
    OK = 0,
    INVALID_ARGUMENT = -1,
    PERMISSION_DENIED = -2,
    RESOURCE_UNAVAILABLE = -3,
    UNKNOWN_ERROR = -100
};
枚举使用规范:
  • 必须指定底层类型,常用 int32_t 或 uint32_t。
  • 建议显式赋值,避免依赖默认值导致跨版本兼容问题。
  • VTS 测试会验证枚举值是否在合法范围内,非法值会导致测试失败。

4.5.3 union(联合体)

union 允许在同一内存位置存储不同类型的值,但同一时刻只能使用其中一种类型。HAL 中的 union 通常与 enum 配合使用,通过 discriminator 标识当前有效类型。

enum ValueType : uint8_t {
    INTEGER,
    FLOAT,
    STRING
};

union Value {
    int32_t intValue;
    float floatValue;
    string strValue;
};

struct TypedValue {
    ValueType type;  // discriminator
    Value value;     // 根据 type 选择有效字段
};
HAL 数据类型关系 HAL 数据类型体系 HAL 数据类型 struct 复合数据结构 enum 命名整型常量 union 类型共享存储 数据类型特性对比 • struct:字段按声明顺序连续存储,支持嵌套和变长数组(vec<T>) • enum:必须指定底层整型类型,值从 0 开始递增(可自定义) • union:所有字段共享同一内存空间,需配合 discriminator 标识当前有效类型 • VTS 测试需验证数据类型的序列化/反序列化一致性,确保跨进程传输正确

4.6 数据类型在 VTS 测试中的验证要点

VTS 测试框架在验证 HAL 接口时,会对数据类型的以下方面进行严格检查:

  1. 类型一致性:验证 .hal 文件中声明的类型与 HAL 实现中的类型完全匹配。
  2. 内存布局:验证 struct 的字段顺序、对齐方式和填充字节是否符合规范。
  3. 枚举值范围:验证枚举值是否在合法范围内,越界值应被拒绝。
  4. 联合体判别器:验证 union 的 discriminator 与有效字段的一致性。
  5. 变长数组边界:验证 vec<T> 的长度是否在合理范围内,防止缓冲区溢出。
测试建议:在编写 VTS 测试用例时,应覆盖数据类型的边界条件,如空数组、最大长度数组、枚举边界值、嵌套结构体的深度等,确保 HAL 实现的健壮性。

4.7 本章小结

本章详细讲解了 .hal 文件的语法结构,包括 package 声明、interface 定义、方法签名以及 struct/enum/union 三种复合数据类型。掌握这些基础知识是进行 VTS 测试框架集成和 HAL 层接口协议验证的前提。在实际测试工作中,需要结合具体 HAL 接口的 .hal 文件,逐项验证语法规范和数据类型的正确性。