3. 属性配置与注册:属性配置文件、权限、变更模式与访问模式

在 Vehicle HAL 中,属性(Property)是车辆信号与上层服务之间的核心数据单元。每个属性在被系统使用之前,必须通过 属性配置文件 完成定义与注册。本章节将深入解析 VehiclePropertyConfig 的结构、属性权限模型、变更模式以及访问模式,帮助开发者构建安全、高效的车辆信号订阅体系。

3.1 属性配置文件(VehiclePropertyConfig)

VehiclePropertyConfig 是描述一个车辆属性元数据的核心结构体。它定义了属性的唯一标识、数据类型、访问权限、变更行为以及支持的车辆区域。该配置通常在 HAL 实现层的 onCreate() 方法中通过列表形式注册。

配置字段 类型 说明
prop int32_t 属性唯一 ID,由 VehicleProperty 枚举定义
access VehiclePropertyAccess 访问模式:读、写、读写
changeMode VehiclePropertyChangeMode 变更模式:静态、连续变化、按需变化
minSampleRate float 最低采样率(Hz),用于连续变化属性
maxSampleRate float 最高采样率(Hz),用于连续变化属性
areaConfigs vector<VehicleAreaConfig> 区域配置列表,定义属性在哪些车辆区域生效
configArray vector<int32_t> 厂商自定义配置数组,用于扩展属性行为
configString string 厂商自定义配置字符串
关键设计原则: 每个属性必须且只能注册一次。重复注册相同 prop ID 会导致 HAL 服务启动失败。区域配置 areaConfigs 必须与属性支持的区域类型(如全局、车窗、车门等)严格匹配。

3.2 属性权限模型

属性权限通过 VehiclePropertyAccess 枚举定义,决定了上层应用或服务能够对属性执行的操作。权限模型是车辆安全策略的第一道防线。

  • READ(读):允许订阅者读取属性的当前值。适用于传感器数据、状态指示等只读信号。
  • WRITE(写):允许订阅者向属性写入新值。适用于控制类信号,如车窗升降、门锁控制。
  • READ_WRITE(读写):同时允许读取和写入。适用于可读可控制的属性,如空调温度设定。
安全警告: 对于涉及行车安全的属性(如车速、制动状态),应严格限制为 READ 模式。任何写操作都可能引入安全风险。对于控制类属性,建议在 HAL 层实现额外的权限校验逻辑。

3.3 变更模式(Change Mode)

变更模式定义了属性值发生变化时的通知策略。正确选择变更模式直接影响系统性能和信号订阅的实时性。

变更模式 枚举值 行为描述 典型应用
STATIC 0x00 属性值在车辆生命周期内不会改变,仅在初始化时设置一次 车辆 VIN、硬件版本号、固件版本
ON_CHANGE 0x01 属性值发生变化时主动通知订阅者,不变化时不发送 车门状态、车窗位置、灯光开关
CONTINUOUS 0x02 属性值以固定采样率持续上报,即使值未变化也可能周期性发送 车速、发动机转速、电池电压
性能优化建议: 对于 CONTINUOUS 模式,务必合理设置 minSampleRate 和 maxSampleRate。过高的采样率会占用大量系统带宽,而过低的采样率可能导致关键信号丢失。通常车速信号建议 10-50 Hz,温度信号 1-5 Hz。

3.4 访问模式(Access Mode)与订阅关系

访问模式决定了订阅者与属性之间的交互方式。在 Vehicle HAL 中,访问模式与变更模式共同决定了属性在订阅系统中的行为特征。

属性配置与注册核心流程 VehiclePropertyConfig 属性配置定义 Access 权限校验 READ / WRITE / READ_WRITE ChangeMode 策略 STATIC / ON_CHANGE / CONTINUOUS areaConfigs 区域绑定 全局 / 车窗 / 车门 / 座椅 采样率范围 minSampleRate ~ maxSampleRate onCreate() 中注册属性列表 将配置对象添加到 VehicleHalServer 的属性集合 订阅者 1 读取 / 写入 订阅者 2 仅读取 订阅规则 访问模式决定 读写权限

3.5 属性注册代码示例

以下代码展示了如何在 HAL 实现中创建并注册一个车速属性(VEHICLE_SPEED)和一个车门状态属性(DOOR_POSITION)。

// VehicleHalServer.cpp 中的 onCreate() 方法
Return<void> onCreate() override {
    // 创建属性配置列表
    std::vector<VehiclePropertyConfig> configs;

    // 1. 车速属性:连续变化,只读,全局区域
    VehiclePropertyConfig speedConfig;
    speedConfig.prop = (int32_t)VehicleProperty::VEHICLE_SPEED;
    speedConfig.access = VehiclePropertyAccess::READ;
    speedConfig.changeMode = VehiclePropertyChangeMode::CONTINUOUS;
    speedConfig.minSampleRate = 10.0f;  // 最低 10 Hz
    speedConfig.maxSampleRate = 50.0f;  // 最高 50 Hz
    // 全局区域配置
    VehicleAreaConfig areaConfig;
    areaConfig.areaId = 0;  // 全局区域 ID
    areaConfig.minInt32Value = 0;
    areaConfig.maxInt32Value = 300;  // 车速范围 0-300 km/h
    speedConfig.areaConfigs = {areaConfig};
    configs.push_back(speedConfig);

    // 2. 车门状态属性:按需变化,读写,按车门区域
    VehiclePropertyConfig doorConfig;
    doorConfig.prop = (int32_t)VehicleProperty::DOOR_POSITION;
    doorConfig.access = VehiclePropertyAccess::READ_WRITE;
    doorConfig.changeMode = VehiclePropertyChangeMode::ON_CHANGE;
    // 四个车门区域配置
    for (int32_t doorId = 1; doorId <= 4; ++doorId) {
        VehicleAreaConfig areaCfg;
        areaCfg.areaId = doorId;
        areaCfg.minInt32Value = 0;   // 关闭
        areaCfg.maxInt32Value = 100; // 完全打开
        doorConfig.areaConfigs.push_back(areaCfg);
    }
    configs.push_back(doorConfig);

    // 注册到 HAL 服务
    auto status = mHalServer->registerProperties(configs);
    if (status != StatusCode::OK) {
        ALOGE("属性注册失败: %d", (int32_t)status);
    }
    return Void();
}
最佳实践: 属性注册应在 onCreate() 中尽早完成,确保在 HAL 服务对外提供信号之前所有元数据已就绪。对于 CONTINUOUS 模式,建议在车辆网络信号稳定后再开始上报,避免启动阶段产生无效数据。

3.6 属性配置与订阅的映射关系

属性配置直接影响订阅者的行为。下表总结了不同配置组合下订阅者的典型表现:

访问模式 变更模式 订阅者读取行为 订阅者写入行为 通知触发条件
READ STATIC 可读取固定值 不允许 无(值不变)
READ ON_CHANGE 可读取当前值 不允许 值发生变化时
READ CONTINUOUS 可读取当前值 不允许 按采样率周期性触发
READ_WRITE ON_CHANGE 可读取当前值 允许写入新值 值发生变化时(包括写入后)
READ_WRITE CONTINUOUS 可读取当前值 允许写入新值 按采样率周期性触发
常见错误: 将 WRITE 模式与 STATIC 变更模式组合是无效的,因为静态属性不允许写入。同样,WRITE 模式与 CONTINUOUS 组合虽然语法上允许,但实际场景中极少使用,因为连续上报通常用于传感器数据,而传感器数据通常是只读的。