赞
踩
前面的文章中,描述了 Android Automotive 的框架中应用、Framework 层服务等知识,本篇文章将会继续按照 Android Automotive 框架介绍 Vehicle Hal 层服务的内容。
上一篇:AndroidAutomotive模块介绍(三)CarService服务
本篇文档将对 Andorid Automotive 框架中 VehicleHal 层展开介绍。VehicleHal 即为车辆硬件抽象层的定义。可以理解为 Android Automotive OS 中的硬件抽象层接口,包括车辆属性和方法;各厂商制造商会根据定义的 Hal 接口,实现定制化的模块服务。
VehicleHal 是链接 Android Automotive Car Services 与制造商实现车辆控制服务进程的桥梁,通过标准化接口对上层提供服务,对于服务的实现依赖厂商的定制化,可以忽略汽车制造商的具体实现,也就是说 CarService 调用 VehicleHal 定义的标准接口,厂商实现这些接口。
VehicleHal 的代码路径为:android/hardware/interfaces/automotive/vehicle/2.0/default。路径下有 android.hardware.automotive.vehicle@2.0-service.rc 文件,在开机阶段通过此 rc 文件,将 VehicleHal 进程启动,下面来看下 android.hardware.automotive.vehicle@2.0-service.rc 文件的定义
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
class hal
user vehicle_network
group system inet
对于 VehicleHal 的编译,可以对以下两个 Android.bp 文件介绍。
VehicleHal 定义的 Hal 接口编译介绍,Android.bp 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0,目录结构如下:
ubuntu:android/hardware/interfaces/automotive/vehicle/2.0$ ls -l
total 132
-rw-r--r-- 1 users 375 Nov 9 2022 Android.bp
drwxrwxr-x 5 users 4096 Mar 22 13:55 default
-rw-r--r-- 1 users 2336 Nov 9 2022 IVehicleCallback.hal
-rw-r--r-- 1 users 3665 Nov 9 2022 IVehicle.hal
-rw-r--r-- 1 users 115184 Nov 9 2022 types.hal
下面是 Android.bp 文件的定义:
// This file is autogenerated by hidl-gen -Landroidbp. hidl_interface { name: "android.hardware.automotive.vehicle@2.0", root: "android.hardware", vndk: { enabled: true, }, srcs: [ "types.hal", "IVehicle.hal", "IVehicleCallback.hal", ], interfaces: [ "android.hidl.base@1.0", ], gen_java: true, }
编译文件中定义了 android.hardware.automotive.vehicle@2.0 HIDL 接口编译,包含三个文件 types.hal、IVehicle.hal、IVehicleCallback.hal 文件。
VehicleHal 服务编译介绍,Android.bp 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default,目录结构如下:
ubuntu16:android/hardware/interfaces/automotive/vehicle/2.0/default$ ls -l
total 28
-rw-r--r-- 1 users 4705 Nov 9 2022 Android.bp
-rw-r--r-- 1 users 155 Nov 9 2022 android.hardware.automotive.vehicle@2.0-service.rc
drwxrwxr-x 4 users 4096 Jun 7 2022 common
drwxrwxr-x 3 users 4096 Jun 7 2022 impl
drwxrwxr-x 2 users 4096 Nov 9 2022 tests
-rw-r--r-- 1 users 1953 Nov 9 2022 VehicleService.cpp
Android.bp 文件定义如下:
// Vehicle reference implementation lib cc_library { name: "android.hardware.automotive.vehicle@2.0-manager-lib", vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ "common/src/Obd2SensorStore.cpp", "common/src/SubscriptionManager.cpp", "common/src/VehicleHalManager.cpp", "common/src/VehicleObjectPool.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", "common/src/VmsUtils.cpp", ], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["common/include"], } // Vehicle default VehicleHAL implementation cc_library_static { name: "android.hardware.automotive.vehicle@2.0-default-impl-lib", vendor: true, cflags: ["-Wno-unused-parameter", "-Wno-sign-compare"], defaults: ["vhal_v2_0_defaults"], srcs: [ "impl/vhal_v2_0/CommConn.cpp", "impl/vhal_v2_0/EmulatedVehicleHal.cpp", "impl/vhal_v2_0/VehicleEmulator.cpp", "impl/vhal_v2_0/PipeComm.cpp", "impl/vhal_v2_0/SocketComm.cpp", "impl/vhal_v2_0/LinearFakeValueGenerator.cpp", "impl/vhal_v2_0/JsonFakeValueGenerator.cpp", ], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["impl"], whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"], shared_libs: [ "libbase", "libprotobuf-cpp-lite", ], static_libs: [ "libjsoncpp", "libqemu_pipe", "android.hardware.automotive.vehicle@2.0-libproto-native", ], } cc_binary { name: "android.hardware.automotive.vehicle@2.0-service", defaults: ["vhal_v2_0_defaults"], init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"], vendor: true, relative_install_path: "hw", srcs: ["VehicleService.cpp"], shared_libs: [ "libbase", "libprotobuf-cpp-lite", ], static_libs: [ "android.hardware.automotive.vehicle@2.0-manager-lib", "android.hardware.automotive.vehicle@2.0-default-impl-lib", "android.hardware.automotive.vehicle@2.0-libproto-native", "libjsoncpp", "libqemu_pipe", ], }
从 Android.bp 的定义中,VehicleHal 的服务名为 android.hardware.automotive.vehicle@2.0-service,启动 rc 文件是 android.hardware.automotive.vehicle@2.0-service.rc,入口文件是 VehicleService.cpp,依赖自定义相关模块主要有 android.hardware.automotive.vehicle@2.0-manager-lib、android.hardware.automotive.vehicle@2.0-default-impl-lib、android.hardware.automotive.vehicle@2.0-libproto-native。
android.hardware.automotive.vehicle@2.0-manager-lib 模块是 common 目录下的文件所编译的内容,主要是 VehicleHal 所以来的模块。
android.hardware.automotive.vehicle@2.0-default-impl-lib 模块是 impl 目录下的文件所编译的内容,主要是 VehicleHal 的功能实现模块。
android.hardware.automotive.vehicle@2.0-libproto-native 模块是 impl/vhal_v2_0/proto 目录下的文件所编译的内容,目录下的文件为 VehicleHalProto.proto 文件,是一种序列化存储数据的方式。
Android Automotive 框架中 Hal 层接口文件有三个,IVehicle.hal、IVehicleCallback.hal 和 types.hal 文件。IVehicle.hal 文件中定义了 Vehicle Hal 对外提供的接口;IVehicleCallback.hal 文件中定义了 VehicleHal 的回调接口;types.hal 文件定义了 Vehicle Hal 的属性定义。
Hidl 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0。
IVehicle.hal 文件中定义了 Vehicle Hal 对外提供的接口,上层 CarService 通过 IVehicle.hal 中定义的接口与 Vehicle Hal 通信。
package android.hardware.automotive.vehicle@2.0; import IVehicleCallback; interface IVehicle { /** * Returns a list of all property configurations supported by this vehicle * HAL. * 返回此车辆HAL支持的所有属性配置的列表 */ getAllPropConfigs() generates (vec<VehiclePropConfig> propConfigs); /** * Returns a list of property configurations for given properties. * * If requested VehicleProperty wasn't found it must return * StatusCode::INVALID_ARG, otherwise a list of vehicle property * configurations with StatusCode::OK * 返回给定属性的属性配置列表。 * 如果请求的车辆属性没有找到,它必须返回StatusCode::INVALID_ARG,否则返回一个车辆属性配置列表,StatusCode::OK */ getPropConfigs(vec<int32_t> props) generates (StatusCode status, vec<VehiclePropConfig> propConfigs); /** * Get a vehicle property value. * * For VehiclePropertyChangeMode::STATIC properties, this method must always * return the same value always. * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the * latest available value. * * Some properties like RADIO_PRESET requires to pass additional data in * GET request in VehiclePropValue object. * * If there is no data available yet, which can happen during initial stage, * this call must return immediately with an error code of * StatusCode::TRY_AGAIN. * 获取车辆属性值。 * 对于 VehiclePropertyChangeMode::STATIC 的属性值,此方法会返回同一个值,不会改变。 * 对于 VehiclePropertyChangeMode::ON_CHANGE 的属性值,此方法会返回最新值。 */ get(VehiclePropValue requestedPropValue) generates (StatusCode status, VehiclePropValue propValue); /** * Set a vehicle property value. * * Timestamp of data must be ignored for set operation. * * Setting some properties require having initial state available. If initial * data is not available yet this call must return StatusCode::TRY_AGAIN. * For a property with separate power control this call must return * StatusCode::NOT_AVAILABLE error if property is not powered on. * 设置车辆属性值。 * 特殊场景: * 设置一些属性值需要其初始状态可用,如果初始状态不可用,需要返回 StatusCode::TRY_AGAIN。 * 设置单独电源控制的属性,如果属性未上电,需要返回 StatusCode::TRY_AGAIN。 */ set(VehiclePropValue propValue) generates (StatusCode status); /** * Subscribes to property events. * * Clients must be able to subscribe to multiple properties at a time * depending on data provided in options argument. * * @param listener This client must be called on appropriate event. * @param options List of options to subscribe. SubscribeOption contains * information such as property Id, area Id, sample rate, etc. * 订阅属性 * 客户端可以一次订阅多个属性,这取决于 options 定义的参数。 * 参数 SubscribeOptions 包含 属性id、区域id、采样率 等信息。 */ subscribe(IVehicleCallback callback, vec<SubscribeOptions> options) generates (StatusCode status); /** * Unsubscribes from property events. * * If this client wasn't subscribed to the given property, this method * must return StatusCode::INVALID_ARG. * 取消订阅属性 * 如果客户端在此前没有对此属性进行订阅,则返回 StatusCode::INVALID_ARG。 */ unsubscribe(IVehicleCallback callback, int32_t propId) generates (StatusCode status); /** * Print out debugging state for the vehicle hal. * * The text must be in ASCII encoding only. * * Performance requirements: * * The HAL must return from this call in less than 10ms. This call must avoid * deadlocks, as it may be called at any point of operation. Any synchronization * primitives used (such as mutex locks or semaphores) must be acquired * with a timeout. * * 打印车辆的调试状态。 */ debugDump() generates (string s); };
IVehicleCallback.hal 文件定义了 VehicleHal 的回调对象,上层 CarService 通过注册此回调对象以监听属性是否改变。VehicleHal 通过回调对象返回状态给到客户端。
package android.hardware.automotive.vehicle@2.0; interface IVehicleCallback { /** * Event callback happens whenever a variable that the API user has * subscribed to needs to be reported. This may be based purely on * threshold and frequency (a regular subscription, see subscribe call's * arguments) or when the IVehicle#set method was called and the actual * change needs to be reported. * * These callbacks are chunked. * * @param values that has been updated. * 当需要报告客户端订阅的变量时,就会调用此回调函数。 * 这可能基于常规按频率上报或者客户端调用 IVehicle#set 函数时调用。 */ oneway onPropertyEvent(vec<VehiclePropValue> propValues); /** * This method gets called if the client was subscribed to a property using * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called. * * These events must be delivered to subscriber immediately without any * batching. * * @param value Value that was set by a client. * 如果客户端使用 SubscribeFlags::EVENTS_FROM_ANDROID 标志订阅属性,并且调用 IVehicle#set 函数,则回调此方法。 */ oneway onPropertySet(VehiclePropValue propValue); /** * Set property value is usually asynchronous operation. Thus even if * client received StatusCode::OK from the IVehicle::set(...) this * doesn't guarantee that the value was successfully propagated to the * vehicle network. If such rare event occurs this method must be called. * * @param errorCode - any value from StatusCode enum. * @param property - a property where error has happened. * @param areaId - bitmask that specifies in which areas the problem has * occurred, must be 0 for global properties * 设置属性通常是异步操作,客户端调用 IVehicle#set 函数到接收到 StatusCode::OK 的返回值,也不能保证此属性成功传播到车辆网络,如果发生这种低概率的事件,则回调此方法。 * @ errorCode:StatusCode 枚举中的任何值。 * @ property:发生错误的属性。 * @ areaId:指定问题发生在哪个区域的位掩码,对于全局属性必须为 0。 */ oneway onPropertySetError(StatusCode errorCode, int32_t propId, int32_t areaId); };
types.hal 中定义了 VehicleHal 的属性、结构等数据。
下面列举 types.hal 中定义的 VehiclePropertyType 属性:
package android.hardware.automotive.vehicle@2.0; /** * Enumerates supported data type for VehicleProperty. * 枚举 VehicleProperty 支持的数据类型。 * Used to create property ID in VehicleProperty enum. * 用于在 VehicleProperty enum 中创建属性 ID。 */ enum VehiclePropertyType : int32_t { // VehicleProperty 的类型是 string、bool、还是 int32 等等 STRING = 0x00100000, BOOLEAN = 0x00200000, INT32 = 0x00400000, INT32_VEC = 0x00410000, INT64 = 0x00500000, INT64_VEC = 0x00510000, FLOAT = 0x00600000, FLOAT_VEC = 0x00610000, BYTES = 0x00700000, /** * Any combination of scalar or vector types. The exact format must be * provided in the description of the property. */ MIXED = 0x00e00000, // 这两个主要就是 VehicleProperty 用来进行或运算的。 MASK = 0x00ff0000 };
下面是 types.hal 中定义的车辆区域属性:
/** * Vehicle Areas * Used to construct property IDs in the VehicleProperty enum. * 用于在VehicleProperty enum中构造属性id。 * * Some properties may be associated with particular vehicle areas. For * example, VehicleProperty:DOOR_LOCK property must be associated with * particular door, thus this property must be marked with * VehicleArea:DOOR flag. * 某些属性可能与特定车辆区域相关。例如,VehicleProperty:DOOR_LOCK 属性必须与特定的门相关联,因此该属性必须标记为 VehicleArea: door 标志。 * * Other properties may not be associated with particular vehicle area, * these kind of properties must have VehicleArea:GLOBAL flag. * 其他属性可能不与特定的车辆区域相关联,这些属性必须具有VehicleArea:GLOBAL标志。 * * [Definition] Area: An area represents a unique element of an AreaType. * For instance, if AreaType is WINDOW, then an area may be FRONT_WINDSHIELD. * * [Definition] AreaID: An AreaID is a combination of one or more areas, * and is represented using a bitmask of Area enums. Different AreaTypes may * not be mixed in a single AreaID. For instance, a window area cannot be * combined with a seat area in an AreaID. * * Rules for mapping a zoned property to AreaIDs: * - A property must be mapped to an array of AreaIDs that are impacted when * the property value changes. * - Each element in the array must represent an AreaID, in which, the * property value can only be changed together in all the areas within * an AreaID and never independently. That is, when the property value * changes in one of the areas in an AreaID in the array, then it must * automatically change in all other areas in the AreaID. * - The property value must be independently controllable in any two * different AreaIDs in the array. * - An area must only appear once in the array of AreaIDs. That is, an * area must only be part of a single AreaID in the array. * * [Definition] Global Property: A property that applies to the entire car * and is not associated with a specific area. For example, FUEL_LEVEL, * HVAC_STEERING_WHEEL_HEAT. * * Rules for mapping a global property to AreaIDs: * - A global property must not be mapped to AreaIDs. */ enum VehicleArea : int32_t { GLOBAL = 0x01000000, // 全局区域 /** WINDOW maps to enum VehicleAreaWindow */ WINDOW = 0x03000000, // 窗户区域 /** MIRROR maps to enum VehicleAreaMirror */ MIRROR = 0x04000000, // 反光镜区域 /** SEAT maps to enum VehicleAreaSeat */ SEAT = 0x05000000, // 座椅区域 /** DOOR maps to enum VehicleAreaDoor */ DOOR = 0x06000000, // 车门区域 /** WHEEL maps to enum VehicleAreaWheel */ WHEEL = 0x07000000, // 车轮区域 YFVehicleAreaTire = 0x08000000, MASK = 0x0f000000, };
下面是 types.hal 中定义的车辆属性分组类型:
/** * Enumerates property groups. * 车辆属性分组枚举 * * Used to create property ID in VehicleProperty enum. * 用于在VehicleProperty enum中创建属性ID。 */ enum VehiclePropertyGroup : int32_t { // AndroidO 之后的 treble,用于区分 android 原生的 property 和厂商的 property。 /** * Properties declared in AOSP must use this flag. * AOSP 原生的属性标志 */ SYSTEM = 0x10000000, /** * Properties declared by vendors must use this flag. * 厂商自定义的属性标志 */ VENDOR = 0x20000000, MASK = 0xf0000000, };
下面是 types.hal 中定义的车辆属性
/** * Declares all vehicle properties. VehicleProperty has a bitwise structure. * Each property must have: * - a unique id from range 0x0100 - 0xffff * - associated data type using VehiclePropertyType * - property group (VehiclePropertyGroup) * - vehicle area (VehicleArea) * * Vendors are allowed to extend this enum with their own properties. In this * case they must use VehiclePropertyGroup:VENDOR flag when property is * declared. * * When a property's status field is not set to AVAILABLE: * - IVehicle#set may return StatusCode::NOT_AVAILABLE. * - IVehicle#get is not guaranteed to work. * * Properties set to values out of range must be ignored and no action taken * in response to such ill formed requests. */ enum VehicleProperty : int32_t { /** Undefined property. */ INVALID = 0x00000000, /** * VIN of vehicle * 车辆 VIN 码 * * @change_mode VehiclePropertyChangeMode:STATIC * @access VehiclePropertyAccess:READ */ INFO_VIN = ( 0x0100 | VehiclePropertyGroup:SYSTEM // 原生属性 | VehiclePropertyType:STRING // 属性值是 String 类型 | VehicleArea:GLOBAL), // 全局属性 /** * Model of vehicle * 车辆型号 * * @change_mode VehiclePropertyChangeMode:STATIC * @access VehiclePropertyAccess:READ */ INFO_MODEL = ( 0x0102 | VehiclePropertyGroup:SYSTEM // 原生属性 | VehiclePropertyType:STRING // 属性值是 String 类型 | VehicleArea:GLOBAL), // 全局属性 ... };
下面是 types.hal 中定义的车辆座位占用状态值
/**
* Used by seat occupancy to enumerate the current occupancy state of the seat.
* 由座位占用使用,以枚举座位的当前占用状态
*/
enum VehicleSeatOccupancyState : int32_t {
UNKNOWN = 0,
VACANT = 1, // 空闲
OCCUPIED = 2 // 占用
};
下面是 types.hal 中定义的灯光状态属性
/**
* Used by lights state properties to enumerate the current state of the lights.
* 由灯光状态属性使用,枚举灯光的当前状态。
* Most XXX_LIGHTS_STATE properties will only report ON and OFF states. Only
* the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
* 大多数 XXX_LIGHTS_STATE 属性将只报告 ON 和 OFF 状态。只有 headlight_state 属性会报告 DAYTIME_RUNNING。
*/
enum VehicleLightState : int32_t {
OFF = 0,
ON = 1,
DAYTIME_RUNNING = 2
};
下面是 types.hal 中定义的车灯开关属性
/** * Used by lights switch properties to enumerate user selected switch setting. * 由灯开关属性使用,枚举用户选择的开关设置。 * XXX_LIGHTS_SWITCH properties report the switch settings that the user * selects. The switch setting may be decoupled from the state reported if the * user selects AUTOMATIC. * XXX_LIGHTS_SWITCH 属性报告用户选择的开关设置。如果用户选择 AUTOMATIC,开关设置可能与报告的状态分离。 */ enum VehicleLightSwitch : int32_t { OFF = 0, ON = 1, /** * Daytime running lights mode. Most cars automatically use DRL but some * cars allow the user to activate them manually. * 日间行车灯模式。大多数汽车自动使用DRL,但有些汽车允许用户手动激活它们。 */ DAYTIME_RUNNING = 2, /** * Allows the vehicle ECU to set the lights automatically * 允许车辆ECU自动设置灯光 */ AUTOMATIC = 0x100, };
下面是 types.hal 中定义的车辆充电连接线类型属性
/** * Used by INFO_EV_CONNECTOR_TYPE to enumerate the type of connectors * available to charge the vehicle. * 由 INFO_EV_CONNECTOR_TYPE 使用,枚举可用于给车辆充电的连接器类型。 */ enum EvConnectorType : int32_t { /** * Default type if the vehicle does not know or report the EV connector * type. * 如果车辆不知道或不报告EV连接器类型,则默认类型 */ UNKNOWN = 0, IEC_TYPE_1_AC = 1, // aka Yazaki IEC_TYPE_2_AC = 2, // aka Mennekes IEC_TYPE_3_AC = 3, // aka Scame IEC_TYPE_4_DC = 4, // aka CHAdeMO IEC_TYPE_1_CCS_DC = 5, // aka Combo 1 IEC_TYPE_2_CCS_DC = 6, // aka Combo 2 TESLA_ROADSTER = 7, TESLA_HPWC = 8, TESLA_SUPERCHARGER = 9, GBT_AC = 10, GBT_DC = 11, /** * Connector type to use when no other types apply. Before using this * value, work with Google to see if the EvConnectorType enum can be * extended with an appropriate value. */ OTHER = 101, };
下面是 types.hal 中定义的用于枚举燃油门或燃油口位置属性。
/** * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or * ev port location. * 用于描述 INFO_FUEL_DOOR_LOCATION 和 INFO_CHARGE_PORT_LOCATION 信号的燃油门或燃油口位置。 */ enum PortLocationType : int32_t { /** * Default type if the vehicle does not know or report the Fuel door * and ev port location. */ UNKNOWN = 0, FRONT_LEFT = 1, FRONT_RIGHT = 2, REAR_RIGHT = 3, REAR_LEFT = 4, FRONT = 5, REAR = 6, };
下面是 types.hal 中定义的风扇方向属性。
/**
* Bit flags for fan direction
* 风扇方向的位标志
*/
enum VehicleHvacFanDirection : int32_t {
FACE = 0x1,
FLOOR = 0x2,
DEFROST = 0x4,
};
下面是 types.hal 中定义的车辆油量属性。
enum VehicleOilLevel : int32_t {
/**
* Oil level values
*/
CRITICALLY_LOW = 0,
LOW = 1,
NORMAL = 2,
HIGH = 3,
ERROR = 4,
};
下面是 types.hal 中定义的车辆输入事件属性。
enum VehicleHwKeyInputAction : int32_t {
/** Key down */
ACTION_DOWN = 1, // 输入事件按下
/** Key up */
ACTION_UP = 0, // 输入事件抬起
};
下面是 types.hal 中定义的属性是否可以改变的配置。
/** * This describes how value of property can change. * 描述属性是否可以改变 */ enum VehiclePropertyChangeMode : int32_t { /** * Property of this type must never be changed. Subscription is not supported * for these properties. * STATIC 表示属性不可修改 */ STATIC = 0x00, /** * Properties of this type must report when there is a change. * IVehicle#get call must return the current value. * Set operation for this property is assumed to be asynchronous. When the * property is read (using IVehicle#get) after IVehicle#set, it may still * return old value until underlying H/W backing this property has actually * changed the state. Once state is changed, the property must dispatch * changed value as event. * ON_CHANGE 表示属性必须在改变时报告 */ ON_CHANGE = 0x01, /** * Properties of this type change continuously and require a fixed rate of * sampling to retrieve the data. Implementers may choose to send extra * notifications on significant value changes. * CONTINUOUS 属性在不断变化,需要固定的速率来检索数据 */ CONTINUOUS = 0x02, };
下面是 types.hal 中定义的车辆属性访问配置。
/**
* Property config defines the capabilities of it. User of the API
* must first get the property config to understand the output from get()
* commands and also to ensure that set() or events commands are in sync with
* the expected output.
* 属性定义功能访问模式。
*/
enum VehiclePropertyAccess : int32_t {
NONE = 0x00,
READ = 0x01, // 只读
WRITE = 0x02, // 只写
READ_WRITE = 0x03, // 读写
};
下面是 types.hal 中定义的车辆属性状态。
/** * Property status is a dynamic value that may change based on the vehicle state. * 属性状态是一个动态值,可能会根据车辆状态而改变。 */ enum VehiclePropertyStatus : int32_t { /** Property is available and behaving normally */ AVAILABLE = 0x00, // 属性可用且运行正常 /** * A property in this state is not available for reading and writing. This * is a transient state that depends on the availability of the underlying * implementation (e.g. hardware or driver). It MUST NOT be used to * represent features that this vehicle is always incapable of. A get() of * a property in this state MAY return an undefined value, but MUST * correctly describe its status as UNAVAILABLE A set() of a property in * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore * the value of the status field when writing a property value coming from * Android. */ UNAVAILABLE = 0x01, // 处于此状态的属性不可用于读写。这是一种瞬态,依赖于底层实现的可用性(例如硬件或驱动程序)。 /** There is an error with this property. */ ERROR = 0x02, };
下面是 types.hal 中定义的汽车齿轮属性。
/** * Various gears which can be selected by user and chosen in system. * 各种齿轮可由用户选择,并在系统中选择。 */ enum VehicleGear : int32_t { GEAR_NEUTRAL = 0x0001, GEAR_REVERSE = 0x0002, GEAR_PARK = 0x0004, GEAR_DRIVE = 0x0008, GEAR_1 = 0x0010, GEAR_2 = 0x0020, GEAR_3 = 0x0040, GEAR_4 = 0x0080, GEAR_5 = 0x0100, GEAR_6 = 0x0200, GEAR_7 = 0x0400, GEAR_8 = 0x0800, GEAR_9 = 0x1000, };
下面是 types.hal 中定义的汽车座椅区域属性。
/**
* Various Seats in the car.
* 汽车里的各种座位。
*/
enum VehicleAreaSeat : int32_t {
ROW_1_LEFT = 0x0001,
ROW_0_CENTER = 0x0002,
ROW_1_RIGHT = 0x0004,
ROW_2_LEFT = 0x0010,
ROW_2_CENTER = 0x0020,
ROW_2_RIGHT = 0x0040,
ROW_3_LEFT = 0x0100,
ROW_3_CENTER = 0x0200,
ROW_3_RIGHT = 0x0400
};
下面是 types.hal 中定义的汽车玻璃区域属性。
/** * Various windshields/windows in the car. * 汽车的各种挡风玻璃/窗户。 */ enum VehicleAreaWindow : int32_t { FRONT_WINDSHIELD = 0x00000001, // 前挡风玻璃 REAR_WINDSHIELD = 0x00000002, // 后挡风玻璃 ROW_1_LEFT = 0x00000010, ROW_1_RIGHT = 0x00000040, ROW_2_LEFT = 0x00000100, ROW_2_RIGHT = 0x00000400, ROW_3_LEFT = 0x00001000, ROW_3_RIGHT = 0x00004000, ROOF_TOP_1 = 0x00010000, ROOF_TOP_2 = 0x00020000, };
下面是 types.hal 中定义的车辆门区域属性。
enum VehicleAreaDoor : int32_t {
ROW_1_LEFT = 0x00000001,
ROW_1_RIGHT = 0x00000004,
ROW_2_LEFT = 0x00000010,
ROW_2_RIGHT = 0x00000040,
ROW_3_LEFT = 0x00000100,
ROW_3_RIGHT = 0x00000400,
HOOD = 0x10000000,
REAR = 0x20000000,
};
下面是 types.hal 中定义的车辆镜子区域属性。
enum VehicleAreaMirror : int32_t {
DRIVER_LEFT = 0x00000001,
DRIVER_RIGHT = 0x00000002,
DRIVER_CENTER = 0x00000004,
};
下面是 types.hal 中定义的车辆转向灯属性。
enum VehicleTurnSignal : int32_t {
NONE = 0x00,
RIGHT = 0x01,
LEFT = 0x02,
};
下面是 types.hal 中定义的车辆区域配置结构体。
struct VehicleAreaConfig { /** * Area id is ignored for VehiclePropertyGroup:GLOBAL properties. * 对于全局属性,忽略 Area 区域 id。 */ int32_t areaId; /** * If the property has @data_enum, leave the range to zero. * * Range will be ignored in the following cases: * - The VehiclePropertyType is not INT32, INT64 or FLOAT. * - Both of min value and max value are zero. */ int32_t minInt32Value; int32_t maxInt32Value; int64_t minInt64Value; int64_t maxInt64Value; float minFloatValue; float maxFloatValue; };
下面是 types.hal 中定义的车辆属性配置。
struct VehiclePropConfig { // Vehicle Property 的配置 /** Property identifier */ int32_t prop; // property 标识符 /** * Defines if the property is read or write or both. */ VehiclePropertyAccess access; // 定义属性是读还是写,还是两者兼而有之 /** * Defines the change mode of the property. */ VehiclePropertyChangeMode changeMode; // 定义属性的更改模式 /** * Contains per-area configuration. */ vec<VehicleAreaConfig> areaConfigs; // 包含每个区域的配置 /** Contains additional configuration parameters */ vec<int32_t> configArray; // 包含其他配置参数 /** * Some properties may require additional information passed over this * string. Most properties do not need to set this. */ string configString; // 某些属性可能需要通过该字符串传递额外的信息 /** * Min sample rate in Hz. * Must be defined for VehiclePropertyChangeMode::CONTINUOUS */ float minSampleRate; // 最小采样率(Hz) /** * Must be defined for VehiclePropertyChangeMode::CONTINUOUS * Max sample rate in Hz. */ float maxSampleRate; // 最大采样率(Hz) };
下面是 types.hal 中定义的车辆属性值。
/** * Encapsulates the property name and the associated value. It * is used across various API calls to set values, get values or to register for * events. * 封装属性名和关联值。它在各种 API 调用中用于设置值、获取值或注册事件。 */ struct VehiclePropValue { /** Time is elapsed nanoseconds since boot */ int64_t timestamp; // 从 boot 开始的时间 /** * Area type(s) for non-global property it must be one of the value from * VehicleArea* enums or 0 for global properties. * 对于非全局属性,区域类型必须是VehicleArea*枚举中的值之一;对于全局属性必须是0。 */ int32_t areaId; /** Property identifier */ int32_t prop; // 属性标识符 /** Status of the property */ VehiclePropertyStatus status; // 属性状态 /** * Contains value for a single property. Depending on property data type of * this property (VehiclePropetyType) one field of this structure must be filled in. * 包含单个属性的值。根据该属性的属性数据类型(vehiclepetytype),必须填充该结构的一个字段。 */ struct RawValue { /** * This is used for properties of types VehiclePropertyType#INT * and VehiclePropertyType#INT_VEC */ vec<int32_t> int32Values; /** * This is used for properties of types VehiclePropertyType#FLOAT * and VehiclePropertyType#FLOAT_VEC */ vec<float> floatValues; /** This is used for properties of type VehiclePropertyType#INT64 */ vec<int64_t> int64Values; /** This is used for properties of type VehiclePropertyType#BYTES */ vec<uint8_t> bytes; /** This is used for properties of type VehiclePropertyType#STRING */ string stringValue; }; RawValue value; };
下面是 VehicleHal 的类图
下面是 VehicleHal 启动序列图
VehicleHal 的入口文件是 VehicleService.cpp。路径为:android/hardware/interfaces/automotive/vehicle/2.0/default。下面是 VehicleService.cpp 的内容:
#define LOG_TAG "automotive.vehicle@2.0-service" #include <android/log.h> #include <hidl/HidlTransportSupport.h> #include <iostream> #include <vhal_v2_0/VehicleHalManager.h> #include <vhal_v2_0/EmulatedVehicleHal.h> using namespace android; using namespace android::hardware; using namespace android::hardware::automotive::vehicle::V2_0; int main(int /* argc */, char* /* argv */ []) { // 创建 VehiclePropertyStore 对象 auto store = std::make_unique<VehiclePropertyStore>(); // 创建 EmulatedVehicleHal 对象 auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get()); // 创建 VehicleEmulator 对象 auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get()); // 创建 VehicleHalManager 对象 auto service = std::make_unique<VehicleHalManager>(hal.get()); configureRpcThreadpool(4, true /* callerWillJoin */); // 注册 VehicleService 服务 ALOGI("Registering as service..."); status_t status = service->registerAsService(); if (status != OK) { ALOGE("Unable to register vehicle service (%d)", status); return 1; } ALOGI("Ready"); joinRpcThreadpool(); return 1; }
从 VehicleService.cpp 中可以发现,主要初始化了 Vehicle 相关服务类,并注册 Vehicle 服务。下面可以来简单跟踪下各类的功能。
VehiclePropertyStore 类是用于封装与存储和访问配置、存储和修改车辆属性值相关的工作。内部主要维护一个 PropertyMap mPropertyValues,PropertyMap = std::map<RecordId, VehiclePropValue>;用于通过 RecordId 保存对应的 VehiclePropValue 值。
VehiclePropValue.h :
android/hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
VehiclePropertyStore.cpp :
android/hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
车辆属性在 VehiclePropertyStore 是存储在有序的 Map 集合中,这样可以更加方便的获取属性的值。VehiclePropertyStore 的使用是线程安全的,方法间使用同步阻塞保证线程安全。
下面是 VehiclePropertyStore.h 头文件的内容:
class VehiclePropertyStore { public: /* Function that used to calculate unique token for given VehiclePropValue */ using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>; private: // 定义 RecordConfig 结构体 struct RecordConfig { VehiclePropConfig propConfig; TokenFunction tokenFunction; }; // 定义 RecordId 结构体 struct RecordId { int32_t prop; // propid int32_t area; // areaid int64_t token; bool operator==(const RecordId& other) const; bool operator<(const RecordId& other) const; }; // 定义 RecordId 和 vehiclePropValue 对应的 Map 集合 using PropertyMap = std::map<RecordId, VehiclePropValue>; using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>; public: // 注册 Property 函数 void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr); /* Stores provided value. Returns true if value was written returns false if config for * example wasn't registered. */ // 写入 VehiclePropValue 值 bool writeValue(const VehiclePropValue& propValue, bool updateStatus); // 移除 VehiclePropValue 值 void removeValue(const VehiclePropValue& propValue); // 通过 propId 移除 VehiclePropValue 值 void removeValuesForProperty(int32_t propId); // 获取所有的 VehiclePropValue 值 std::vector<VehiclePropValue> readAllValues() const; std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const; std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const; std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0, int64_t token = 0) const; // 获取所有的 VehiclePropConfig 值 std::vector<VehiclePropConfig> getAllConfigs() const; // 根据 propId 获取 VehiclePropConfig 值 const VehiclePropConfig* getConfigOrNull(int32_t propId) const; const VehiclePropConfig* getConfigOrDie(int32_t propId) const; private: RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const; const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const; PropertyMapRange findRangeLocked(int32_t propId) const; private: using MuxGuard = std::lock_guard<std::mutex>; mutable std::mutex mLock; std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs; PropertyMap mPropertyValues; // Sorted map of RecordId : VehiclePropValue. };
EmulatedVehicleHal 的文件路径如下:
EmulatedVehicleHal.h 路径为:
android/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
EmulatedVehicleHal.cpp 路径为:
android/hardware/interfaces/automotive/vehicle/2.0/defaultandroid/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
EmulatedVehicleHal 可以理解为 VehicleHal 功能的真正实施类,EmulatedVehicleHal 实现了 EmulatedVehicleHalIface 和 VehicleHal 的功能。上层的 Binder 在 Hal 层的流转后,最终是通过 EmulatedVehicleHal 去处理的。下面是 EmulatedVehicleHal 头文件的内容:
class EmulatedVehicleHal : public EmulatedVehicleHalIface { // EmulatedVehicleHalIface 继承了 VehicleHal public: EmulatedVehicleHal(VehiclePropertyStore* propStore); ~EmulatedVehicleHal() = default; // Methods from VehicleHal // 实现了 VehicleHal 接口功能,上层的 Binder 调用会调用到这里 void onCreate() override; std::vector<VehiclePropConfig> listProperties() override; VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue, StatusCode* outStatus) override; StatusCode set(const VehiclePropValue& propValue) override; StatusCode subscribe(int32_t property, float sampleRate) override; StatusCode unsubscribe(int32_t property) override; // Methods from EmulatedVehicleHalIface // 实现了 EmulatedVehicleHalIface 接口功能 bool setPropertyFromVehicle(const VehiclePropValue& propValue) override; std::vector<VehiclePropValue> getAllProperties() const override; private: constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const { return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz)); } StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request); void onFakeValueGenerated(const VehiclePropValue& value); VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param); VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay); void onContinuousPropertyTimer(const std::vector<int32_t>& properties); bool isContinuousProperty(int32_t propId) const; void initStaticConfig(); void initObd2LiveFrame(const VehiclePropConfig& propConfig); void initObd2FreezeFrame(const VehiclePropConfig& propConfig); StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue, VehiclePropValue* outValue); StatusCode fillObd2DtcInfo(VehiclePropValue* outValue); StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue); /* Private members */ VehiclePropertyStore* mPropStore; std::unordered_set<int32_t> mHvacPowerProps; RecurrentTimer mRecurrentTimer; GeneratorHub mGeneratorHub; };
VehicleEmulator 的文件路径如下:
VehicleEmulator.h 的文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
VehicleEmulator.cpp 的文件路径为:
android/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
VehicleEmulator 的解释是通过 ADB 或 Pipe 从主机端提供控制接口来模拟车辆。
VehicleEmulator 可以理解为通过 SPI 通信与 MCU 芯片建立通信,连通车身 Can 网络来获取车辆的信号的处理类。厂商基于 VehicleEmulator 的功能搭建厂商自身的车身通信功能,例如通过 DBus 与 MCU 通信,获取来自 MCU 的车身数据;MCU 通过 Can 网络获取车身其他固件,例如空调、座椅等其他 ECU 件的数据。
下面是 VehicleEmulator.h 文件的内容:
class VehicleEmulator; // Forward declaration. /** Extension of VehicleHal that used by VehicleEmulator. */ // 定义 EmulatedVehicleHalIface 类,扩展 VehicleHal 接口。 class EmulatedVehicleHalIface : public VehicleHal { public: virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0; virtual std::vector<VehiclePropValue> getAllProperties() const = 0; void registerEmulator(VehicleEmulator* emulator) { ALOGI("%s, emulator: %p", __func__, emulator); std::lock_guard<std::mutex> g(mEmulatorLock); mEmulator = emulator; } protected: VehicleEmulator* getEmulatorOrDie() { std::lock_guard<std::mutex> g(mEmulatorLock); if (mEmulator == nullptr) abort(); return mEmulator; } private: mutable std::mutex mEmulatorLock; VehicleEmulator* mEmulator; }; /** * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe. */ // 定义 VehicleEmulator 类,通过 socket、pipe 模拟车辆 class VehicleEmulator : public MessageProcessor { public: VehicleEmulator(EmulatedVehicleHalIface* hal); virtual ~VehicleEmulator(); void doSetValueFromClient(const VehiclePropValue& propValue); void processMessage(emulator::EmulatorMessage const& rxMsg, emulator::EmulatorMessage& respMsg) override; private: friend class ConnectionThread; using EmulatorMessage = emulator::EmulatorMessage; void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg); void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg, const VehiclePropConfig& cfg); void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal, const VehiclePropValue* val); private: EmulatedVehicleHalIface* mHal; std::unique_ptr<SocketComm> mSocketComm; std::unique_ptr<PipeComm> mPipeComm; };
VehicleHalManager 的文件路径如下:
VehicleHalManager.h 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
VehicleHalManager.cpp 文件路径为:
android/hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
VehicleHalManager 类是 IVehicle HIDL 接口和厂商实现之间的一个代理。VehicleHalManager 直接继承了 IVehicle,上层调用 Hild 接口时,会最先调用到此类中,VehicleHalManager 在初始化时获取 VehicleHal 对象,厂商需要实现 VehicleHal 类以提供 VehicleHal 的功能。
下面是 VehicleHalManager.h 文件的内容:
/** * This class is a thick proxy between IVehicle HIDL interface and vendor's implementation. * * It has some boilerplate code like batching and caching property values, checking permissions, * etc. Vendors must implement VehicleHal class. */ // VehicleHalManager 继承 IVehicle 类,提供 Hidl 接口调用 class VehicleHalManager : public IVehicle { public: // 构造函数需要传入 VehicleHal 类对象,具体 Hidl 接口功能实现由 VehicleHal 提供 VehicleHalManager(VehicleHal* vehicleHal) : mHal(vehicleHal), mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed, this, std::placeholders::_1)) { init(); } virtual ~VehicleHalManager(); void init(); // --------------------------------------------------------------------------------------------- // Methods derived from IVehicle 实现 Hidl 接口函数 Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) override; Return<void> getPropConfigs(const hidl_vec<int32_t>& properties, getPropConfigs_cb _hidl_cb) override; Return<void> get(const VehiclePropValue& requestedPropValue, get_cb _hidl_cb) override; Return<StatusCode> set(const VehiclePropValue& value) override; Return<StatusCode> subscribe(const sp<IVehicleCallback>& callback, const hidl_vec<SubscribeOptions>& options) override; Return<StatusCode> unsubscribe(const sp<IVehicleCallback>& callback, int32_t propId) override; Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override; private: using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr; // Returns true if needs to call again shortly. using RetriableAction = std::function<bool()>; // --------------------------------------------------------------------------------------------- // Events received from VehicleHal void onHalEvent(VehiclePropValuePtr v); void onHalPropertySetError(StatusCode errorCode, int32_t property, int32_t areaId); // --------------------------------------------------------------------------------------------- // This method will be called from BatchingConsumer thread void onBatchHalEvent(const std::vector<VehiclePropValuePtr >& values); void handlePropertySetEvent(const VehiclePropValue& value); const VehiclePropConfig* getPropConfigOrNull(int32_t prop) const; bool checkWritePermission(const VehiclePropConfig &config) const; bool checkReadPermission(const VehiclePropConfig &config) const; void onAllClientsUnsubscribed(int32_t propertyId); static bool isSubscribable(const VehiclePropConfig& config, SubscribeFlags flags); static bool isSampleRateFixed(VehiclePropertyChangeMode mode); static float checkSampleRate(const VehiclePropConfig& config, float sampleRate); static ClientId getClientId(const sp<IVehicleCallback>& callback); private: VehicleHal* mHal; // 保存 VehicleHal 对象 std::unique_ptr<VehiclePropConfigIndex> mConfigIndex; SubscriptionManager mSubscriptionManager; hidl_vec<VehiclePropValue> mHidlVecOfVehiclePropValuePool; ConcurrentQueue<VehiclePropValuePtr> mEventQueue; BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer; VehiclePropValuePool mValueObjectPool; };
本篇主要描述了 Android 原生的 Automotive 框架中 VehicleHal 的逻辑。简单来说,VehicleHal 层主要是完成了对上层 Hidl 接口功能的实现,具体实现依赖厂商的逻辑,从框架上是封装了厂商的 VechielHal 实现,提供车辆网络信号的设置和获取功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。