车机技术之Android Automotive
借助各种总线拓扑,很多汽车子系统都可以实现互连以及与车载信息娱乐 (IVI) 系统的连接。根据制造商不同,所提供的确切总线类型和协议也有很大差异(甚至同一品牌的不同车型之间也是如此);示例包括控制器区域网络 (CAN) 总线、本地互联网络 (LIN) 总线、媒体导向系统传输 (MOST) 总线以及汽车级以太网和 TCP/IP 网络(例如 BroadR-Reach)。
Android Automotive 的硬件抽象层 (HAL) 为 Android 框架提供了一致的接口(无需考虑物理传输层)。此车载 HAL 是用于开发 Android Automotive 实现的接口。
系统集成人员可以将特定于功能的平台 HAL 接口(如 HVAC)与特定于技术的网络接口(如 CAN 总线)连接,以实现车载 HAL 模块。典型的实现可能包括运行专有实时操作系统 (RTOS) 的专用微控制器单元(MCU,用于 CAN 总线访问或类似操作),该微控制器单元可通过串行链路连接到运行 Android Automotive 的 CPU。除了专用的 MCU,您还可以将总线访问作为虚拟 CPU 来实现。只要实现符合车载 HAL 的接口要求,每个合作伙伴都可以选择适合硬件的架构。
架构
车载 HAL 是汽车与车辆网络服务之间的接口定义:
图 1. 车载 HAL 与 Android Automotive 架构
- Car API:包含 CarHvacManager、CarSensorManager 和 CarCameraManager 等 API。如需详细了解受支持的 API,请参阅 /platform/packages/services/Car/car-lib。
- CarService:位于/platform/packages/services/Car/。
- VehicleNetworkService:通过内置安全机制来控制车载 HAL。仅限系统组件使用(第三方应用等非系统组件应使用汽车 API)。原始设备制造商 (OEM) 可以通过 vns_policy.xml 和vendor_vns_policy.xml 控制访问权限。位于 /platform/packages/services/Car/vehicle_network_service/;要查看用于访问车辆网络的库,请参阅/platform/packages/services/Car/libvehiclenetwork/。
- 车载 HAL:定义 OEM 可以实现的车辆属性的接口。包含属性元数据(例如,车辆属性是否为 int 以及允许使用哪些更改模式)。位于hardware/libhardware/include/hardware/vehicle.h。要了解基本参考实现的相关信息,请参阅hardware/libhardware/modules/vehicle/。
有关更多详情参考下面的“车辆属性”章节。
安全性
车载 HAL 支持 3 个级别的数据访问安全性:
- 仅限系统(由 vns_policy.xml 控制)
- 允许拥有权限的应用进行访问(通过汽车服务)
- 无需任何权限即可访问(通过汽车服务)
仅允许部分系统组件直接访问车辆属性,而车辆网络服务是把关程序。大多数应用都需要通过汽车服务的额外把关(例如,只有系统应用可以控制 HVAC,因为系统权限只能授予系统应用)。
验证
AOSP 包含开发过程中使用的以下测试资源:
- hardware/libhardware/tests/vehicle/vehicle-hal-tool.c
加载车载 HAL 并执行简单操作的命令行原生工具。它有助于系统在开发的早期阶段启动并运行。 - packages/services/Car/tests/carservice_test/
包含使用模拟车载 HAL 属性进行的汽车服务测试。每个属性的预期行为都会在测试中实现,这是了解预期行为的绝佳起点。 - hardware/libhardware/modules/vehicle/
基本参考实现。
车辆属性
车载 HAL 接口会定义原始设备制造商 (OEM) 可以实现的属性,并会包含属性元数据(例如,属性是否为 int 以及允许使用哪些更改模式)。车载 HAL 接口是以对属性(特定功能的抽象表示)的访问(读取、写入、订阅)为基础。
HAL 接口
车载 HAL 使用以下接口:
- vehicle_prop_config_t const *(*list_properties)(…, int* num_properties)
列出车载 HAL 所支持的所有属性的配置。车辆网络服务只会使用受支持的属性。 - (*get)(…, vehicle_prop_value_t *da
ta)
读取属性的当前值。对于区域属性,每个区域都可能具有不同的值。 - (*set)(…, const vehicle_prop_value_t *da
ta)
为属性写入相应值。写入的结果是按属性进行定义。 - (*subscribe)(…, int32_t prop, float sample_rate, int32_t zones)
- 开始监视属性值的变化。对于区域属性,订阅适用于请求的区域。“zones = 0”用于请求所有受支持的区域。
- 车载 HAL 应该在属性值发生变化时(即 on-change 类型)或按一定间隔(即 continuous 类型)调用单独的回调。
- (*release_memory_from_get)(struct vehicle_hw_device* device, vehicle_prop_value_t *da
ta)
释放从 get 调用分配的内存。
车载 HAL 使用以下回调接口:
- (*vehicle_event_callback_fn)(const vehicle_prop_value_t *event_da
ta)
通知车辆属性值的变化。应只针对已订阅属性执行。 - (*vehicle_error_callback_fn)(int32_t error_co
de, int32_t property, int32_t operation)
返回全局车载 HAL 级错误或每个属性的错误。全局错误会导致 HAL 重新启动,这可能导致包括应用在内的其他组件重新启动。
车辆属性
属性可以是只读、只写(用于将信息传递到车载 HAL 一级),也可以是能够读取和写入(对大多数属性而言支持读写是可选的)。每个属性都由 int32 键唯一标识,且具有预定义的类型 (value_type):
- INT32(和数组)、INT64、BOOLEAN、FLOAT(和数组)、字符串、字节。
- 区域类型除了值之外还有区域。
区域类型
车载 HAL 定义了 3 种区域类型:
- vehicle_zone
基于排的区域。 - vehicle_seat
基于座位的区域。 - vehicle_window
基于窗户的区域。
每个区域属性都应使用预定义的区域类型。如有必要,您可以为每个属性都使用自定义区域类型(有关详情,请参阅“处理自定义属性”一节)。
配置属性
请使用 vehicle_prop_config_t 为每个属性提供配置信息。具体信息包括:
- access(r、w、rw)
- change_mode(表示监视属性的方式:on-change 模式还是 continuous 模式)
- min_value(int32、float、int64)、max_value(int32、float、int64)
- min_sample_rate、max_sample_rate
- permission_model
- prop(属性 ID、int)
- value_type
- zone_flags(将受支持的区域表示为位标记)
此外,某些属性具有表示功能的具体配置标记。
处理区域属性
区域属性相当于多个属性的集合,其中每个子属性都可由指定的区域值访问。
- 区域属性的 get 调用请求中始终包含区域,因此,只应返回所请求区域的当前值。
- 区域属性的 set 调用请求中始终包含区域,因此,只应更改所请求的区域。
- subscribe 调用包含所有已订阅区域的标记。不应报告来自未订阅区域的事件。
get 调用
在初始化期间,由于尚未收到匹配的车辆网络消息,因此属性的值可能不可用。在这种情况下,get 调用应该返回 -EAGAIN。某些属性(如 HVAC)具有单独的电源开/关属性。关机时这种属性的 get 调用应返回特殊值 (VEHICLE_INT_OUT_OF_RANGE_OFF / VEHICLE_FLOAT_OUT_OF_RANGE_OFF),而不是返回错误。
此外,某些属性(如 HVAC 温度)可以用某个值来表示其处于最大功率模式,而不是特定的温度值。在这种情况下,请使用特殊值表示这种状态。
- VEHICLE_INT_OUT_OF_RANGE_MAX/MIN
- VEHICLE_FLOAT_OUT_OF_RANGE_MAX/MIN
示例:获取 HVAC 温度
图 2. 获取 HVAC 温度(CS = CarService、VNS = VehicleNetworkService、VHAL = 车载 HAL)
set 调用
set 调用属于异步操作,涉及进行所请求更改之后的事件通知。在典型的操作中,set 调用会导致在车辆网络中发出更改请求。拥有该属性的电子控制单元 (ECU) 执行更改后,更新后的值会通过车辆网络返回,而车载 HAL 会将更新后的值作为事件发送给车辆网络服务 (VNS)。
某些 set 调用可能要求准备好初始数据,而这些数据在初始化期间可能尚未提供。在这种情况下,set 调用应该返回 -EAGAIN。某些具有单独的电源开/关的属性应在电源关闭且无法设置时返回 -ESHUTDOWN。
在 set 生效之前,get 不一定会返回所设置的值。不过,例外的是更改模式为 VEHICLE_PROP_CHANGE_MODE_ON_SET的属性。此类属性仅在被 Android 之外的外部组件(如 VEHICLE_PROPERTY_UNIX_TIME 等时钟属性)设置时才会通知更改。
示例:设置 HVAC 温度:
图 3. 设置 HVAC 温度(CD = CarService、VNS = VehicleNetworkService、VHAL = 车载 HAL)
处理自定义属性
为了满足合作伙伴的特定需求,车载 HAL 允许使用仅限于系统应用的自定义属性。在使用自定义属性时,请遵循以下指南:
- 键应该处于 [VEHICLE_PROPERTY_CUSTOM_START, VEHICLE_PROPERTY_CUSTOM_END] 范围内。其他范围已预留下来以供将来扩展;使用这些范围可能会导致在将来的 Android 版本中出现冲突。
- 仅使用定义的 value_type。BYTES 类型允许传递原始数据,因此,在大多数情况下这就足够了。通过自定义属性频繁发送大数据可能会减缓整个车辆网络的访问速度,因此,在添加大量需要 HAL 处理的数据时要小心谨慎。
- 将访问策略添加到 vendor_vns_policy.xml(否则所有访问都会被拒)。
- 通过 Vendor Extension Manager(适用于 Java 组件)或 Vehicle Network Service API(适用于原生代码)访问。请勿修改其他汽车 API,因为这样做可能会在将来导致兼容性问题。
处理 HVAC 属性
您可以通过设置与 HVAC 相关的属性,来使用车载 HAL 控制 HVAC。大多数 HVAC 属性都是区域属性,但也有一些非区域(全局)属性。定义的示例属性包括:
- VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET
按区域设置温度。 - VEHICLE_PROPERTY_HVAC_RECIRC_ON
按区域控制再循环。
有关 HVAC 属性的完整列表,请在 vehicle.h 中搜索 VEHICLE_PROPERTY_HVAC_*。
处理传感器属性
车载 HAL 传感器属性表示实际的传感器数据或策略信息,如驾驶状况。某些传感器信息(如驾驶状况和日间/夜间模式)不限制任何应用的访问,因为这些数据是构建安全车载应用所必需的。还有一些传感器信息(如车辆速度)更为敏感,需要用户可以管理的特定权限。
支持的传感器属性包括:
- DRIVING_STATUS
应该支持。表示在当前驾驶状态下允许的操作。此信息用于在驾驶过程中屏蔽不安全的应用。 - NIGHT_MODE
应该支持。确定日间/夜间显示模式。 - GEAR_SELECTION/CURRENT_GEAR
驾驶员选择的挡位与实际挡位。 - VEHICLE_SPEED
车速。受权限保护。 - ODOMETER
当前里程表读数。受权限保护。 - FUEL_LEVEL
当前油位 (%)。 - FUEL_LEVEL_LOW
油位是否较低(布尔值)。