前言:
本文是车载Android之核心服务-CarPropertyService的第二篇,了解一下CarPropertyService的VehicleHAL, 第一篇在车载 Android之 核心服务 – CarPropertyService 解析-CSDN博客,有兴趣的 朋友可以去看下。
本节介绍 AndroidAutomotiveOS中对于 VehicleHAL,即车辆硬件抽象层的定义。
前文中多次提到了 VehicleHAL,当提起 VehicleHAL的时候,它可能包含以下含义。
(1)由 AndroidAutomotiveOS定义的硬件抽象层接口,包括车辆属性和方法;
(2)由制造商根据硬件抽象层定义所实现的服务进程;
(3)在 CarService中,由Java实现的 VehicleHal辅助类。
而在本节中,VehicleHAL主要指代的是第一种含义。而制造商提供的 VehicleHal服务进程是业务逻辑主要的实现者,非常重要,但只要满足了硬件抽象层所定义的方法和 行为,各制造商的具体实现可能很不一样,没有统一的范式,因此在本节中不过多展开分析。
VehicleHAL是连通 CarService与制造商实现的车辆控制服务进程的桥梁,其中包括 种类繁多的车辆属性。那么,各种各样的车辆属性是如何被定义的? 有什么规则可循? 要 找到这些 问 题 的 答 案,就 需 要 更 深 入 地 了 解 VehicleHAL。本 节 通 过 源 码 进 一 步 分 析 VehicleHAL。
说到 VehicleHAL,就 需 要 先 简 单 解 释 HAL 层 的 概 念。HAL 层 即 硬 件 抽 象 层 (HardwareAbstractionLayer)的缩写。按照谷歌官方的说法①,HAL 可定义一个标准接 口以供硬件供应商实现,这可让 Android忽略较低级别的驱动程序实现。
根据上面的定义,就能知道 VehicleHAL 是车辆硬件抽象层。它的作用是定义了标准 的接口,让 CarService可以忽略各个汽车制造商的具体实现。换句话说,CarService调用 VehicleHAL定义的接口,而制造商们负责实现这些接口。
下面来看 VehicleHAL的具体内容。
VehicleHAL 的源码位于 hardware/interfaces/automotive/vehicle/2.0/路径下(截至 本书完成时,最新的 VehicleHAL版本为2.0)。主要的文件只有三个:
- IVehicle.hal。
- IVehicleCallback.hal。
- types.hal。
这三个文件的定义方式、语法都遵循了 Android8.0中提出的 HIDL的定义规范②,这 里不做展开,有兴趣的读者可以阅读谷歌官网上的相关资料。
其中,IVehicle.hal、IVehicleCallback.hal的定义都很简单,这两个文件中定义的是具 体的类和方法。例如,在IVehicle中定义了获取属性值的 get方法、订阅属性的subscribe 方法;IVehicleCallback中定义了属性变化时的回调方法onPropertyEvent,这些方法在之 前介 绍 CarPropertyService 的 内 容 时 有 所 提 及。 方 法 并 不 多,是 因 为 CarService 与 VehicleHAL的主要实现是基于“属性”的,因此用于定义具体数据结构和属性值的types. hal就显得格外重要了。
1.车辆属性
车辆相关属性值的定义都在types.hal文件中,具体来看types.hal中对各个属性的定 义格式。以 PERF_VEHICLE_SPEED属性为例,它代表了车速信号,具体定义如下:
其中,VehiclePropertyGroup、VehiclePropertyType、VehicleArea这几个枚举类型的定 义同样在该文件中可以找到。这里的 VehiclePropertyGroup:SYSTEM 等于0x10000000,VehiclePropertyType:FLOAT 等于0x00600000,VehicleArea:GLOBAL等于0x01000000。因 此该属性的值就是0x11600207。如果查看 CarSensorManager中车速属性的定义,会发现 该值和 CarSensorManager中的 SENSOR_TYPE_CAR_SPEED 属性的值一模一样,这就 是 CarSensorManager中的车速属性值的原始定义。
VehicleHAL定义了标准的属性名称和值(为了保持版本的兼容性,这些属性值的定义 基本不会发生变化)。制造商在实现汽车服务的时候会通过定义好的属性值区分具体的功 能,同时 CarService中也是通过这些属性来控制具体功能的。
仔细观察属性值的定义可以发现各个属性 的定义并不是随意为之的,而是有它的规则。 每个属性都是通过不同的掩码组合而来,因此 每个 属 性 的 不 同 位 有 各 自 的 含 义。 还 是 以 PERF_VEHICLE_SPEED 属 性 为 例,具 体 情 况如图5-3所示。
这样通过属性的值,使用者就能知道属性 的组别、区域和类型了。其他的属性需要遵循 相同 的 规 则。CarPropertyManager中 涉 及 的 属性虽 然 众 多,但 都 是 根 据 这 样 的 规 则 来 定 义的。
下面对不同位的枚举类型做进一步分析。 VehiclePropertyGroup主要用于区分该属性是 AOSP 定义的还是制造商自定义的, SYSTEM 意味着该值是 AndroidAutomotiveOS的标准定义,任何使用 AndroidAutomotive OS的制造商都需要遵循一样的定义值;而 VENDOR 意味着是制造商自定义的车辆属性, 这些属性对应的功能应该不存在于当前标准的 VehicleHAL 属性列表中,如 VehicleHAL 中已有定义的功能属性,则不应该再重复定义。VehiclePropertyGroup的具体定义如下:
而 VehiclePropertyType则定义了该属性的类型,目前 VehiclePropertyType主要支持 的是一些基本类型,如整型、浮点型、字符串型等,虽然在定义中有 MIXED 这样的复合类型 定义,但是在 CarPropertyService中并不支持复合类型,其主要原因是为了确保数据的通用 性,CarPropertyService本身都是由不同属性、信号所驱动的,单个属性或者说信号的含义 是单一的,这样的好处是维持了不同属性间的颗粒度大致相同。当然,有时候就需要制造商 在增加定义时做比较细的划分了。除此之外,也可以考虑使用字节数组的方式传递一些复 杂类型,并进行序列化和反序列化。VehiclePropertyType的具体定义如下:
VehicleArea则定义了属性所对应的区域值,如车窗、座椅等。用以明确该属性在车辆 上具体的物理位置,具体定义如下:
以上就是车辆属性的具体定义方式,AndroidAutomotiveOS对于车辆硬件抽象层的 定义还是非常简练的。主要体现在:在接口方法上只定义了几个方法,而不同功能是通过 属性ID来进行区分的。这样就可以避免重复定义很多作用类似的set/get接口。当然,定 义虽简单,但是实现起来可就未必了,需要支持如此多的属性。那么就需要汽车制造商在硬 件抽象层好好实现相关的功能了。
2.自定义属性
在之前介绍 CarVendorExtensionManager时提到制造商可根据需要自定义特有的属 性。这部分内容就通过具体的例子说明该如何增加自定义属性。通过前面的介绍,相信读 者已经了解了车辆属性定义的具体规则。自定义属性并不复杂,只需按照规则增加新的属 性就可以了。
首先,根据 HIDL定义的规范,在自定义属性前需要创建新的types.hal文件。假设现 有一款支持“车辆隐身”功能的车型,该功能支持打开和关闭,打开时车就会隐身。这是某品 牌特有的功能,在标准的车辆属性中是没有现成的属性可以使用的,但开发者又期望可以通 65 第 5 章 CarPropertyService———车辆属性服务 过 CarAPI对该功能进行控制。制造商可以通过自定义属性实现这一需求,该属性可能的 定义如下:
由于 是 拓 展 属 性,在 声 明 了 新 定 义 的 属 性 枚 举 名 称 及 包 名 (此 处 取 名 为 vendor. hardware.vehiclevendorextension@1.0)的同时,可以在继承原来标准 VehicleProperty列 表的基础上进行,因此加上android.hardware.automotive.vehicle@2.0::VehicleProperty。 这里有几点是需要注意的。
(1)低四位用以区分不同属性,可以从1开始,随着属性的新增顺序增加。
(2)由于是制造商自定义的属性,因此类别必须是 VehiclePropertyGroup:VENDOR, 用以区别于 AOSP中的属性(VehiclePropertyGroup:SYSTEM)。
(3)VehiclePropertyType代表属性值的类型,包括string、boolean、int32等,可根据实 际属性的类型进行自定义。
(4)VehicleArea代表区域类型,包含 global(全局)、window(车窗)、mirror(反光镜)、 seat(座椅)、door(门)、wheel(车轮)。除了 global,其他区域有更加细分 的 区 域 定 义,如 VehicleAreaWindow、VehicleAreaMirror等。但在定义属性时,只需指定至 VehicleArea就 可以了。
3.VehicleHAL服务进程的实现
到此为止,读者已经了解了 AndroidAutomotiveOS中 VehicleHAL 的主要定义了。 尽管还有很多在types.hal中定义的数据类型没有被提及,但相信读者已经对最主要的车 辆属性及硬件抽象接口是如何定义的有了一个大致的了解。其他在 VehicleHAL中定义的 属性,如输入事件、电源状态等,在后文中还会进一步介绍。
有了车辆 硬 件 抽 象 层 的 定 义,那 么 对 于 制 造 商 而 言 最 重 要 的 工 作 就 是 实 现 一 个 VehicleHAL的服务,为 CarService提供支持。
在这一部分的实现上,各个制造商的实现各有不同。Android在 AOSP的源码中提供 了默 认 的 参 考 实 现。位 于 hardware/interfaces/automotive/vehicle/2.0/default路 径 下。 有兴趣的读者参考其实现。尽管其中并不包含与车辆总线交互这样实际的业务逻辑,但是默认实现中对于 VehicleProperty队列的管理、消息订阅的管理上都提供了一些值得参考的 实践。
制造商该如何具体实现 VehicleHal服务的具体细节在此就不再展开了,笔者在这里也 是抛砖引玉,希望有兴趣或从事相关开发工作的读者可以继续深入学习,结合制造商自身的 软件架构特点实现一个高性能且稳定的汽车服务。