3. 车身属性服务概述

在 Android Automotive 的软件栈中,应用层想要读取车速、空调温度、车门状态、座椅位置等车身信号,不能直接访问 CAN 总线或硬件寄存器,而必须经过一套标准化的属性访问框架。CarPropertyService(简称 CPS)正是这套框架的核心服务,它把底层 VehicleHal 暴露的原始属性,包装成可被 CarPropertyManager 调用的、带权限与订阅机制的 Java API。理解 CPS 的定义、作用以及它与 CarService、VehicleHal、CarPropertyManager 的关系,是后续所有车身属性开发的基础。

一、CarPropertyService 的定义

CarPropertyService 是运行在 CarService 进程中的一个系统服务(System Service),继承自 Android 的 Binder 服务模型,对外通过 ICarProperty AIDL 接口暴露能力。它的本质是一个“属性访问代理与治理层”:向上为应用提供 get/set/subscribe 三类操作,向下把请求翻译成 VehicleHal 的 HAL 调用,并在中间完成权限校验、区域(Area)解析、属性配置校验、订阅分发和速率控制。

从代码结构看,CPS 位于 packages/services/Car/service/src/com/android/car/hal/ 相关包中,核心类包括 CarPropertyService、PropertyHalService、VehicleHal 等。它并不直接持有硬件句柄,而是通过 VehicleHal 这一层与 vendor 实现的 HAL 交互。

核心定位:CarPropertyService = 属性访问的“中间治理层”,负责把 VehicleHal 的原始能力,转化为应用可安全使用的 CarPropertyManager API。

二、CarPropertyService 的核心作用

CPS 的职责可以归纳为五个方面,它们共同构成了车身属性访问的完整闭环:

  • 属性注册与配置管理:启动时从 VehicleHal 拉取所有支持的属性配置(PropertyConfig),包括属性 ID、数据类型、区域类型、访问权限、支持的速率等,形成属性能力清单。
  • 权限与访问控制:根据属性的 access 字段(READ / WRITE / READ_WRITE)和调用方 UID,判断是否允许读取或写入,防止普通应用越权控制车身。
  • 区域(Area)解析:对于座椅、空调、车门等多区域属性,CPS 负责把 AreaId 映射到具体区域,并校验该属性是否支持对应区域。
  • 订阅与事件分发:应用通过 registerCallback 订阅属性变化,CPS 维护订阅列表,在属性值变化时按注册的速率回调给对应应用。
  • 速率控制与去抖:通过 sampleRate 控制属性上报频率,避免高频信号(如车速)无节制地冲击应用层。

三、与 CarService、VehicleHal、CarPropertyManager 的关系

这四个组件构成了车身属性访问的完整链路,理解它们的分工与调用方向,比记住类名更重要。下图展示了它们之间的层次与数据流关系:

应用层 框架层 HAL 层 硬件层 应用 App 调用 CarPropertyManager API 应用 App 注册属性回调监听 CarPropertyManager getProperty / setProperty / registerCallback CarService 进程 CarPropertyService 权限校验 · 区域解析 · 订阅分发 VehicleHal HAL 抽象 · 属性配置缓存 车辆硬件 / CAN 总线 ECU · 传感器 · 执行器 调用 Binder IPC 调用 HIDL / AIDL 属性值上报 回调分发 onChange 回调 实线:请求下行 虚线:数据上行

从图中可以清晰看到四者的分工:

组件 所在层 核心职责 与 CPS 的关系
CarPropertyManager 应用框架层 面向应用的 API 封装,提供 get/set/registerCallback CPS 的客户端代理,通过 Binder 调用 CPS
CarService 系统服务层 车载系统服务容器,管理生命周期与权限 CPS 的宿主进程,CPS 是其内部服务之一
CarPropertyService 系统服务层 属性治理:权限、区域、订阅、速率 核心中间层,连接 Manager 与 VehicleHal
VehicleHal HAL 抽象层 与 vendor HAL 交互,缓存属性配置 CPS 的下游依赖,提供原始属性读写

四、典型调用流程与代码示例

以“读取车速”为例,完整链路如下:应用调用 CarPropertyManager.getProperty(),Manager 通过 Binder 把请求发给 CarPropertyService;CPS 校验权限和属性配置后,调用 VehicleHal 的 get();VehicleHal 再通过 HIDL/AIDL 请求 vendor HAL,最终从 CAN 总线拿到车速并逐层返回。

// 应用侧:通过 CarPropertyManager 读取车速
CarPropertyManager mgr = (CarPropertyManager)
        car.getCarManager(Car.PROPERTY_SERVICE);

// 车速属性:PERF_VEHICLE_SPEED,单位 m/s
float speed = mgr.getFloatProperty(
        VehiclePropertyIds.PERF_VEHICLE_SPEED,
        VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);

// 订阅车速变化,采样率 1Hz
mgr.registerCallback(callback,
        VehiclePropertyIds.PERF_VEHICLE_SPEED,
        1000f);  // sampleRateHz

写入类属性(如空调温度)则走 setProperty,CPS 会额外校验调用方是否具备 WRITE 权限,以及目标区域是否合法。若属性为只读,写入请求会被直接拒绝并记录日志。

五、常见误区与复盘

误区一:把 CarPropertyManager 当成服务本身。它只是应用侧的代理对象,真正的治理逻辑在 CarPropertyService 中。应用崩溃不会影响 CPS,但 CPS 异常会导致所有属性访问失败。
误区二:认为所有属性都能随意订阅。订阅前必须确认属性配置中的 access 包含 READ,且 changeMode 支持 ON_CHANGE 或 CONTINUOUS,否则注册会失败。
复盘建议:排查属性问题时,按“应用 → CarPropertyManager → CarPropertyService → VehicleHal → HAL”的顺序逐层确认。先用 adb shell dumpsys car_service 查看属性配置与订阅状态,再检查 vendor HAL 是否正常上报,能快速定位是权限、区域、速率还是底层信号的问题。

总结来说,CarPropertyService 是 Android Automotive 车身属性访问的中枢:它上承 CarPropertyManager 的应用请求,下接 VehicleHal 的硬件能力,并依托 CarService 进程完成权限与生命周期管理。掌握这四者的层次关系与数据流向,才能在后续的属性配置、订阅优化和问题排查中做到有的放矢。