VHAL(Vehicle Hardware Abstraction Layer) 是连接 Android Framework 与车载 ECU(Electronic Control Units)的桥梁。它提供统一接口,使得上层应用(如 HVAC 控制、仪表盘显示)能访问和控制底层车辆硬件。
Vehicle HAL 定义了车载系统中所有车辆属性(如车速、灯光、空调状态等)的数据格式、范围、作用区域等。
VehiclePropertyGroup
用来给每个 车辆属性(Vehicle Property分类)
aidl
package android.hardware.automotive.vehicle;
@Backing(type="int") @VintfStability
enum VehiclePropertyGroup {
SYSTEM = 0x10000000, // 系统保留属性(AOSP 定义的标准属性)
VENDOR = 0x20000000, // 厂商扩展属性
BACKPORTED = 0x30000000, // 从新版本回移支持到旧版本的属性
MASK = 0xf0000000, // 掩码,用于从 propertyId 中提取 group 信息
}
名称 | 值 | 含义 | 适用场景 |
---|---|---|---|
SYSTEM |
0x10000000 |
标准系统属性(Android AOSP 定义) | 通用属性,如 HVAC_TEMPERATURE_SET 、FUEL_LEVEL |
VENDOR |
0x20000000 |
OEM/厂商自定义属性 | 例如吉利、比亚迪、宝马等定义的专有功能,如按摩座椅控制 |
BACKPORTED |
0x30000000 |
新版本中的属性回移到旧平台 | 某些新功能下沉到旧 Android Automotive 平台时使用 |
MASK |
0xf0000000 |
掩码位 | 从 propertyId 中提取属性归属 group |
VehicleArea
用于标记某个属性 适用于车辆的哪个部分 ------ 比如是整个车辆(Global)、车窗、座椅、门,还是某个厂商自定义区域
aidl
package android.hardware.automotive.vehicle;
@Backing(type="int") @VintfStability
enum VehicleArea {
GLOBAL = 0x01000000, // 全车通用区域,例如油量、车速
WINDOW = 0x03000000, // 车窗相关(左前窗、右后窗等)
MIRROR = 0x04000000, // 后视镜区域(左镜、右镜)
SEAT = 0x05000000, // 座椅区域(主驾、副驾、后排)
DOOR = 0x06000000, // 车门区域(左前门等)
WHEEL = 0x07000000, // 车轮区域(胎压等)
VENDOR = 0x08000000, // 厂商自定义区域
MASK = 0x0f000000, // 区域掩码(用于从 propertyId 提取 area 类型)
}
Area 名称 | 含义 | 适用场景举例 |
---|---|---|
GLOBAL |
全车通用,不区分具体部位 | 车速、电量、电压、温度环境 |
WINDOW |
车窗(窗升降控制) | HVAC_WINDOW_DEFROSTER_ON |
MIRROR |
后视镜 | 调整左后视镜角度 |
SEAT |
座椅控制 | 加热/通风、座椅位置记忆 |
DOOR |
车门 | 锁门、车门状态开关 |
WHEEL |
车轮 | 胎压、轮胎温度 |
VENDOR |
自定义区域 | 比如副驾屏幕触控、第三排座椅 |
VehiclePropertyType
用于标识车辆属性(VehicleProperty)的数据类型。每个车辆属性(比如空调温度、车速、车门状态)都有一个对应的类型,而这个枚举值就是用来表示这个类型的
aidl
package android.hardware.automotive.vehicle;
@Backing(type="int") @VintfStability
enum VehiclePropertyType {
STRING = 0x00100000, // UTF-8 字符串
BOOLEAN = 0x00200000, // 布尔值(true/false)
INT32 = 0x00400000, // 32 位整数
INT32_VEC = 0x00410000, // 整数数组
INT64 = 0x00500000, // 64 位整数
INT64_VEC = 0x00510000, // 64 位整数数组
FLOAT = 0x00600000, // 单个浮点数
FLOAT_VEC = 0x00610000, // 浮点数组
BYTES = 0x00700000, // 任意字节数据
MIXED = 0x00e00000, // 多类型混合结构(复杂结构)
MASK = 0x00ff0000, // 掩码
}
类型名 | 描述 | 示例用途 |
---|---|---|
STRING |
UTF-8 字符串 | 车主名、语言、设备 ID |
BOOLEAN |
布尔值(true/false) | 空调开关、车灯状态 |
INT32 |
32 位整数 | 风速等级、座椅位置 |
INT32_VEC |
整数数组 | 多区域风速、车窗开度等 |
INT64 |
64 位整数 | 时间戳、里程数(高精度) |
INT64_VEC |
64 位整数数组 | 多个传感器的时间戳 |
FLOAT |
单个浮点数 | 温度、车速 |
FLOAT_VEC |
浮点数组 | 方向角、GPS 坐标等 |
BYTES |
任意字节数据 | 图像数据、加密 blob |
MIXED |
多类型混合结构(复杂结构) | 通常用于 OEM 自定义结构(Vendor Extensions) |
MASK |
掩码 | 用于提取类型位 |
VehicleProperty
举几个车辆属性例子
aidl
package android.hardware.automotive.vehicle;
@Backing(type="int") @VintfStability
enum VehicleProperty {
INVALID = 0x00000000,
// 车辆识别码
INFO_VIN = (((0x0100 + 0x10000000) + 0x01000000) + 0x00100000) /* 286261504 */,
// 车辆制造商
INFO_MAKE = (((0x0101 + 0x10000000) + 0x01000000) + 0x00100000) /* 286261505 */,
// 车辆型号
INFO_MODEL = (((0x0102 + 0x10000000) + 0x01000000) + 0x00100000) /* 286261506 */,
// 空调开关
HVAC_POWER_ON = (((0x0510 + 0x10000000) + 0x05000000) + 0x00200000) /* 354419984 */,
//空调风速
HVAC_FAN_SPEED = (((0x0500 + 0x10000000) + 0x05000000) + 0x00400000) /* 356517120 */,
// 空调温度设置
HVAC_TEMPERATURE_SET = (((0x0503 + 0x10000000) + 0x05000000) + 0x00600000) /* 358614275 */,
// 车门是否上锁
DOOR_LOCK = (((0x0B02 + 0x10000000) + 0x06000000) + 0x00200000) /* 371198722 */,
// 车门位置
DOOR_POS = (((0x0B00 + 0x10000000) + 0x06000000) + 0x00400000) /* 373295872 */,
// 车窗位置
WINDOW_POS = (((0x0BC0 + 0x10000000) + 0x03000000) + 0x00400000) /* 322964416 */,
// 移动车窗
WINDOW_MOVE = (((0x0BC1 + 0x10000000) + 0x03000000) + 0x00400000) /* 322964417 */,
// 车窗是否上锁
WINDOW_LOCK = (((0x0BC4 + 0x10000000) + 0x03000000) + 0x00200000) /* 320867268 */,
// 左/右转向灯状态
TURN_SIGNAL_STATE = (((0x0408 + 0x10000000) + 0x01000000) + 0x00400000) /* 289408008 */,
// 雾灯状态
FOG_LIGHTS_STATE = (((0x0E02 + 0x10000000) + 0x01000000) + 0x00400000) /* 289410562 */,
// 是否拉起手刹(布尔值)
PARKING_BRAKE_ON = (((0x0402 + 0x10000000) + 0x01000000) + 0x00200000) /* 287310850 */,
}
VehicleProperty ID 编码结构
32 位 int 类型
- 高位前 4 个 bit 代表 VehiclePropertyGroup
- 4 个 bit 代表 VehicleArea
- 4 个 bit 代表 VehiclePropertyType
- 另外 20个 bit(一般只用到了低位16 bit) 代表属性标识。
sql
31 28 27 24 23 20 19 0
+------------+------------+------------+------------------------+
| Group | Area | Type | Property |
+------------+------------+------------+------------------------+
Vehicle HAL 启动
Vehicle HAL 是由 init 启动的
sql
service vendor.vehicle-hal-emulator /vendor/bin/hw/android.hardware.automotive.vehicle@V3-emulator-service
class early_hal
user vehicle_network
group system inet
android.hardware.automotive.vehicle@V3-emulator-service 源代码
cpp
#define LOG_TAG "EmulatedVehicleService"
#include <DefaultVehicleHal.h>
#include <EmulatedVehicleHardware.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <utils/Log.h>
using ::android::hardware::automotive::vehicle::DefaultVehicleHal;
using ::android::hardware::automotive::vehicle::fake::EmulatedVehicleHardware;
int main(int /* argc */, char* /* argv */[]) {
ALOGI("Starting thread pool...");
// 设置 binder 最大线程数为 4
if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
ALOGE("%s", "failed to set thread pool max thread count");
return 1;
}
// 启动 binder 线程池
ABinderProcess_startThreadPool();
// 创建 EmulatedVehicleHardware 对象
std::unique_ptr<EmulatedVehicleHardware> hardware = std::make_unique<EmulatedVehicleHardware>();
// 创建 DefaultVehicleHal 对象
std::shared_ptr<DefaultVehicleHal> vhal =
::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
ALOGI("Emulator Vehicle Service: Registering as service...");
// DefaultVehicleHal 添加到 servicemanager 服务中
binder_exception_t err = AServiceManager_addService(
vhal->asBinder().get(), "android.hardware.automotive.vehicle.IVehicle/default");
if (err != EX_NONE) {
ALOGE("failed to register android.hardware.automotive.vehicle service, exception: %d", err);
return 1;
}
ALOGI("Emulator Vehicle Service Ready");
// 当前线程加入 binder 线程池
ABinderProcess_joinThreadPool();
ALOGI("Emulator Vehicle Service Exiting");
return 0;
}
EmulatedVehicleHardware 初始化
车辆属性 json 配置文件 /vendor/etc/automotive/vhalconfig/DefaultProperties.json 示例
json
{
"apiVersion": 1,
"properties": [
{
"property": "VehicleProperty::INFO_VIN",
"defaultValue": {
"stringValue": "1GCARVIN123456789"
}
},
{
"property": "VehicleProperty::INFO_MODEL_YEAR",
"defaultValue": {
"int32Values": [
2023
]
}
},
{
"property": "VehicleProperty::HVAC_TEMPERATURE_SET",
"defaultValue": {
"floatValues": [
17.0
]
},
"areas": [
{
"areaId": "Constants::SEAT_1_LEFT",
"minFloatValue": 16.0,
"maxFloatValue": 28.0
},
{
"areaId": "Constants::SEAT_1_RIGHT",
"minFloatValue": 16.0,
"maxFloatValue": 28.0
},
{
"areaId": "Constants::SEAT_2_LEFT",
"minFloatValue": 16.0,
"maxFloatValue": 28.0
},
{
"areaId": "Constants::SEAT_2_RIGHT",
"minFloatValue": 16.0,
"maxFloatValue": 28.0
},
{
"areaId": "Constants::SEAT_2_CENTER",
"minFloatValue": 16.0,
"maxFloatValue": 28.0
}
],
"comment":
"minFloatValue and maxFloatValue in area config should match corresponding values in configArray",
"configArray": [
160,
280,
5,
608,
824,
9
]
}
]
}
cpp
constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/";
constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
// EmulatedVehicleHardware 父类构造函数
FakeVehicleHardware::FakeVehicleHardware()
: FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
// defaultConfigDir 为 /vendor/etc/automotive/vhalconfig/
// overrideConfigDir 为 /vendor/etc/automotive/vhaloverride/
// forceOverride 为 false
FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
std::string overrideConfigDir, bool forceOverride)
: FakeVehicleHardware(defaultConfigDir, overrideConfigDir, forceOverride,
/*s2rS2dConfig=*/
GetIntProperty(POWER_STATE_REQ_CONFIG_PROPERTY, /*default_value=*/0)) {}
// defaultConfigDir 为 /vendor/etc/automotive/vhalconfig/
// overrideConfigDir 为 /vendor/etc/automotive/vhaloverride/
// forceOverride 为 false
// s2rS2dConfig 为 0
FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
std::string overrideConfigDir, bool forceOverride,
int32_t s2rS2dConfig)
: mValuePool(std::make_unique<VehiclePropValuePool>()),
mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
mDefaultConfigDir(defaultConfigDir),
mOverrideConfigDir(overrideConfigDir),
mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
mFakeUserHal(new FakeUserHal(mValuePool)),
mRecurrentTimer(new RecurrentTimer()),
// 事件发生器
mGeneratorHub(new GeneratorHub(
// 当有事件发生后会触发 eventFromVehicleBus()方法
[this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
mPendingGetValueRequests(this),
mPendingSetValueRequests(this),
mForceOverride(forceOverride) {
init(s2rS2dConfig);
}
// VehiclePropValuePool 构造函数
VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240)
: mMaxRecyclableVectorSize(maxRecyclableVectorSize),
mMaxPoolObjectsSize(maxPoolObjectsSize){};
// VehiclePropertyStore 构造函数
explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
: mValuePool(valuePool) {}
// FakeObd2Frame 构造函数
explicit FakeObd2Frame(std::shared_ptr<VehiclePropertyStore> propStore)
: mPropStore(propStore) {}
// FakeUserHal 构造函数
explicit FakeUserHal(std::shared_ptr<VehiclePropValuePool> valuePool) : mValuePool(valuePool) {}
// RecurrentTimer 构造函数
RecurrentTimer::RecurrentTimer() {
// 创建 MessageHandler 消息处理器
mHandler = sp<RecurrentMessageHandler>::make(this);
// 创建 Looper 对象
mLooper = sp<Looper>::make(/*allowNonCallbacks=*/false);
// 创建线程并运行
mThread = std::thread([this] {
// 把 looper 设置为当前线程本地变量中
Looper::setForThread(mLooper);
while (!mStopRequested) {
// 循环获取消息
mLooper->pollOnce(/*timeoutMillis=*/-1);
}
});
}
// GeneratorHub 构造函数
GeneratorHub::GeneratorHub(OnHalEvent&& onHalEvent) : mOnHalEvent(onHalEvent) {
mThread = std::thread(&GeneratorHub::run, this);
}
void GeneratorHub::run() {
//启动线程,循环获取 event
while (!mShuttingDownFlag.load()) {
std::unique_lock<std::mutex> lock(mGeneratorsLock);
ScopedLockAssertion lock_assertion(mGeneratorsLock);
// mEventQueue 默认为 empty
while (!mEventQueue.empty() &&
mGenerators.find(mEventQueue.top().generatorId) == mGenerators.end()) {
mEventQueue.pop();
}
// Wait until event queue is not empty or shutting down flag is set.
// This would unlock mGeneratorsLock and reacquire later.
mCond.wait(lock, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
if (mShuttingDownFlag.load()) {
break;
}
const VhalEvent& curEvent = mEventQueue.top();
long currentTime = elapsedRealtimeNano();
long waitTime =
curEvent.val.timestamp > currentTime ? curEvent.val.timestamp - currentTime : 0;
if (waitTime != 0) {
// Wait until the soonest event happen
if (mCond.wait_for(lock, std::chrono::nanoseconds(waitTime)) !=
std::cv_status::timeout) {
ALOGI("Something happened while waiting");
continue;
}
}
// 处理事件回调
mOnHalEvent(curEvent.val);
// Update queue by popping current event and producing next event from the same generator
int32_t id = curEvent.generatorId;
mEventQueue.pop();
if (mGenerators.find(id) != mGenerators.end()) {
auto maybeNextEvent = mGenerators[id]->nextEvent();
if (maybeNextEvent.has_value()) {
mEventQueue.push({id, maybeNextEvent.value()});
continue;
}
}
ALOGI("%s: Generator ended, unregister it, id: %d", __func__, id);
mGenerators.erase(id);
}
}
void FakeVehicleHardware::eventFromVehicleBus(const VehiclePropValue& value) {
mServerSidePropStore->writeValue(mValuePool->obtain(value));
}
// 调用 init 方法 ,s2rS2dConfig 为 0
void FakeVehicleHardware::init(int32_t s2rS2dConfig) {
maybeGetGrpcServiceInfo(&mPowerControllerServiceAddress);
// loadConfigDeclarations 解析 json 文件,生成 std::unordered_map<int32_t, ConfigDeclaration> 对象
for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
VehiclePropConfig cfg = configDeclaration.config;
VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
// 系统级别的写属性,由 MCU(或电源管理单元)写入,通知 Android 系统即将发生的电源状态变化请求。
if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
cfg.configArray[0] = s2rS2dConfig;
// 如果是 OBD2_FREEZE_FRAME 时 给 tokenFunction 赋值 lambda 表达式
} else if (cfg.prop == OBD2_FREEZE_FRAME) {
tokenFunction = [](const VehiclePropValue& propValue) { return propValue.timestamp; };
}
// 注册为属性
mServerSidePropStore->registerProperty(cfg, tokenFunction);
if (obd2frame::FakeObd2Frame::isDiagnosticProperty(cfg)) {
// 如果为诊断属性,不用设置初始化值
continue;
}
// 存储初始值
storePropInitialValue(configDeclaration);
}
// OBD2_LIVE_FRAME 和 OBD2_FREEZE_FRAME 是在 车载诊断(OBD-II)系统中常见的两种数据帧类型,
// 用于诊断和监控车辆的运行状态
// OBD2_LIVE_FRAME 表示实时的运行数据帧,即当前车辆各个传感器或系统的实时状态
auto maybeObd2LiveFrame = mServerSidePropStore->getPropConfig(OBD2_LIVE_FRAME);
if (maybeObd2LiveFrame.has_value()) {
mFakeObd2Frame->initObd2LiveFrame(maybeObd2LiveFrame.value());
}
// OBD2_FREEZE_FRAME 表示故障发生时刻的快照数据帧,即当故障码(DTC)被记录时,
// 保存下来的那一刻的一组车辆状态。
auto maybeObd2FreezeFrame = mServerSidePropStore->getPropConfig(OBD2_FREEZE_FRAME);
if (maybeObd2FreezeFrame.has_value()) {
mFakeObd2Frame->initObd2FreezeFrame(maybeObd2FreezeFrame.value());
}
// 设置数值变化后的监听器
mServerSidePropStore->setOnValuesChangeCallback([this](std::vector<VehiclePropValue> values) {
return onValuesChangeCallback(std::move(values));
});
}
// 获取配置 json 信息 生成 ConfigDeclaration map
std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
bool defaultConfigLoaded = loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
if (!defaultConfigLoaded) {
// This cannot work without a valid default config.
ALOGE("Failed to load default config, exiting");
exit(1);
}
if (UseOverrideConfigDir()) {
loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
}
return configsByPropId;
}
// dirPath 为 /vendor/etc/automotive/vhalconfig/
bool FakeVehicleHardware::loadPropConfigsFromDir(
const std::string& dirPath,
std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
ALOGI("loading properties from %s", dirPath.c_str());
auto dir = opendir(dirPath.c_str());
if (dir == nullptr) {
ALOGE("Failed to open config directory: %s", dirPath.c_str());
return false;
}
// 读取里面的 json 文件 ,生成 ConfigDeclaration
std::regex regJson(".*[.]json", std::regex::icase);
while (auto f = readdir(dir)) {
if (!std::regex_match(f->d_name, regJson)) {
continue;
}
std::string filePath = dirPath + "/" + std::string(f->d_name);
ALOGI("loading properties from %s", filePath.c_str());
auto result = mLoader.loadPropConfig(filePath);
if (!result.ok()) {
ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
result.error().message().c_str());
continue;
}
for (auto& [propId, configDeclaration] : result.value()) {
(*configsByPropId)[propId] = std::move(configDeclaration);
}
}
closedir(dir);
return true;
}
enum class VehiclePropertyAccess : int32_t {
// 不可访问 ,一般不用,除非你要临时屏蔽某个属性
NONE = 0,
// 只读 ,如:车速、当前油量、电池电压,系统只能读取,不能修改
READ = 1,
// 只写 ,比较少见,用于只能由系统写入的控制类属性
WRITE = 2,
// 可读写,如:HVAC 设置温度、风速、座椅加热等,既可读取状态,也可以修改
READ_WRITE = 3,
};
enum class VehiclePropertyChangeMode : int32_t {
// 值是静态的,设置后不会变 如:VIN 码、车型号、制造日期、最大支持风速等级
// 不会被推送更新,只能手动读取一次;
STATIC = 0,
// 仅在值变化时才通知如:车门是否打开、HVAC 是否开启、安全带状态
// 事件驱动:只有当值变化时才会通知客户端;
ON_CHANGE = 1,
// 持续周期性变化 如:车速、转速、电池电压、加速度、GPS 数据
// 是 周期推送:例如以 10Hz 的频率持续上报;
// 在 VehiclePropConfig 中,minSampleRate 和 maxSampleRate
// 就是给 CONTINUOUS 类型准备的,决定上报的频率范围。
CONTINUOUS = 2,
};
// 属性值
class RawPropValues {
public:
static const char* descriptor;
// int32_t 数组
std::vector<int32_t> int32Values = {};
// float 数组
std::vector<float> floatValues;
// int64_t 数组
std::vector<int64_t> int64Values;
// uint8_t 数组
std::vector<uint8_t> byteValues;
// 字符串
std::string stringValue;
// 跨进程可以通过 Parcel 传输
binder_status_t readFromParcel(const AParcel* parcel);
binder_status_t writeToParcel(AParcel* parcel) const;
}
struct ConfigDeclaration {
// 车辆属性的详细配置信息(定义属性 ID、权限、更新模式、区域等)
VehiclePropConfig config;
// 整个属性的默认初始值(不区分区域)
RawPropValues initialValue;
// 每个区域(areaId)的初始值映射,用于区域性属性(如温度、风速)
std::unordered_map<int32_t, RawPropValues>initialAreaValues;
};
class VehiclePropConfig {
public:
// 类型名,用于序列化/调试输出
static const char* descriptor;
// 属性 ID(例如 VehicleProperty::HVAC_TEMPERATURE_SET),标识一个具体功能项
int32_t prop = 0;
// 属性的读写权限
VehiclePropertyAccess access = VehiclePropertyAccess::NONE;
// 属性的变化通知模式,决定如何触发更新事件
VehiclePropertyChangeMode changeMode = VehiclePropertyChangeMode::STATIC;
// 如果属性支持区域划分(如车窗/座椅),每个区域的详细配置会放在这里
std::vector<VehicleAreaConfig> areaConfigs;
// 自定义参数数组,可由具体平台或 OEM 自定义使用,常用于标志位、参数配置等
std::vector<int32_t> configArray;
// 字符串参数配置,OEM 可定义含义,比如设备路径、标识等
std::string configString;
//最小采样频率(仅对 CONTINUOUS 类型有效),单位 Hz
float minSampleRate = 0.000000f;
//最大采样频率(仅对 CONTINUOUS 类型有效),单位 Hz
float maxSampleRate = 0.000000f;
}
class VehicleAreaConfig {
public:
static const char* descriptor;
// 区域 ID,表示该配置适用于哪个区域(如驾驶位、副驾驶、后排等),区域值是 bitmask 形式
int32_t areaId = 0;
// 若该区域支持 int32 类型输入,该字段表示最小允许值
int32_t minInt32Value = 0;
// 若该区域支持 int32 类型输入,该字段表示最小允许值
int32_t maxInt32Value = 0;
// 若该区域支持 int64 类型输入,该字段表示最大允许值
int64_t minInt64Value = 0L;
// 若该区域支持 int64 类型输入,该字段表示最大允许值
int64_t maxInt64Value = 0L;
// 若该区域支持 float 类型输入,该字段表示最小允许值
float minFloatValue = 0.000000f;
// 若该区域支持 float 类型输入,该字段表示最大允许值
float maxFloatValue = 0.000000f;
// 支持的枚举值(如:风速等级仅支持 1, 2, 3)
std::optional<std::vector<int64_t>> supportedEnumValues;
// 区域内的访问权限(可选覆盖全局 access)
VehiclePropertyAccess access = VehiclePropertyAccess::NONE;
// 是否支持该区域设置不同采样率(仅对 CONTINUOUS 属性有效)
bool supportVariableUpdateRate = false;
}
// 创建一个 Record 存储到 mRecordsByPropId 里面
void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
VehiclePropertyStore::TokenFunction tokenFunc) {
std::scoped_lock<std::mutex> g(mLock);
mRecordsByPropId[config.prop] = Record{
.propConfig = config,
.tokenFunction = tokenFunc,
};
}
struct Record {
VehiclePropConfig propConfig;
TokenFunction tokenFunction;
std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values;
};
// 设置初始值
void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config) {
const VehiclePropConfig& vehiclePropConfig = config.config;
int propId = vehiclePropConfig.prop;
// 判断是否全局属性
bool globalProp = isGlobalProp(propId);
// 如果是全局属性,数量为 1 ,如果是区域对象,获取区域配置的数量
size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();
// 空调开关
if (propId == toInt(VehicleProperty::HVAC_POWER_ON)) {
// 获取 VehicleProperty::HVAC_POWER_ON 配置的 configArray
const auto& configArray = vehiclePropConfig.configArray ;
// 初始化空调开关的依赖属性对象
hvacPowerDependentProps.insert(configArray.begin(), configArray.end());
}
// 初始化属性值
for (size_t i = 0; i < numAreas; i++) {
int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;
// 初始化属性值
VehiclePropValue prop = {
.timestamp = elapsedRealtimeNano(),
.areaId = curArea,
.prop = propId,
.value = {},
};
// 根据配置的值初始化 VehiclePropValue 的 value
if (config.initialAreaValues.empty()) {
if (config.initialValue == RawPropValues{}) {
// Skip empty initial values.
continue;
}
prop.value = config.initialValue;
} else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
valueForAreaIt != config.initialAreaValues.end()) {
prop.value = valueForAreaIt->second;
} else {
ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea);
continue;
}
// 把值写入 mServerSidePropStore
auto result =
mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
if (!result.ok()) {
ALOGE("failed to write default config value, error: %s, status: %d",
getErrorMsg(result).c_str(), getIntErrorCode(result));
}
}
}
// 创建 RecyclableType 对象
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) {
int propId = src.prop;
VehiclePropertyType type = getPropType(propId);
// 获取 VehiclePropValue 大小
size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
auto dest = obtain(type, vectorSize);
dest->prop = propId;
dest->areaId = src.areaId;
dest->status = src.status;
dest->timestamp = src.timestamp;
copyVehicleRawValue(&dest->value, src.value);
return dest;
}
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type, size_t vectorSize) {
// 单一数值,不是数组
if (isSingleValueType(type)) {
vectorSize = 1;
// 字符串 或者 MIXED 类型
} else if (isComplexType(type)) {
vectorSize = 0;
}
// 是否废弃,不缓存到缓存池
return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize)
: obtainRecyclable(type, vectorSize);
}
enum class EventMode : uint8_t {
// 只有当新的属性值(忽略时间戳)不同于旧值时,才会触发回调。
ON_VALUE_CHANGE,
// 无论值是否变化,每次写入/更新都触发回调(包括重复值)。
ALWAYS,
// 永不触发 onValueChangeCallback,仅内部刷新数据。通过定时轮询拉取值,而不是等待回调
NEVER,
};
VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus = false,
EventMode mode = EventMode::ON_VALUE_CHANGE,
bool useCurrentTimestamp = false) EXCLUDES(mLock);
// propValue
// updateStatus 为 true
// eventMode 默认为 EventMode::ON_VALUE_CHANGE
// useCurrentTimestamp 默认为 false
VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus,
VehiclePropertyStore::EventMode eventMode,
bool useCurrentTimestamp) {
bool valueUpdated = true;
VehiclePropValue updatedValue;
OnValueChangeCallback onValueChangeCallback = nullptr;
OnValuesChangeCallback onValuesChangeCallback = nullptr;
int32_t propId;
int32_t areaId;
{
std::scoped_lock<std::mutex> g(mLock);
// useCurrentTimestamp 为 false
if (useCurrentTimestamp) {
propValue->timestamp = elapsedRealtimeNano();
}
propId = propValue->prop;
areaId = propValue->areaId;
// 检查 Record 是否设置
VehiclePropertyStore::Record* record = getRecordLocked(propId);
if (record == nullptr) {
return StatusError(StatusCode::INVALID_ARG)
<< "property: " << propId << " not registered";
}
// 检查 propValue 和 Record 中的 propConfig areaId 是否匹配
if (!isGlobalProp(propId) && getAreaConfig(*propValue, record->propConfig) == nullptr) {
return StatusError(StatusCode::INVALID_ARG)
<< "no config for property: " << propId << " area ID: " << propValue->areaId;
}
// 获取 RecordId
VehiclePropertyStore::RecordId recId = getRecordIdLocked(*propValue, *record);
// 通过 RecordId 从 values 找到对应的 VehiclePropValue
if (auto it = record->values.find(recId); it != record->values.end()) {
const VehiclePropValue* valueToUpdate = it->second.get();
int64_t oldTimestampNanos = valueToUpdate->timestamp;
VehiclePropertyStatus oldStatus = valueToUpdate->status;
// 如何旧的时间大于当前写入的,废弃
if (oldTimestampNanos > propValue->timestamp) {
return StatusError(StatusCode::INVALID_ARG)
<< "outdated timestampNanos: " << propValue->timestamp;
}
if (!updateStatus) {
propValue->status = oldStatus;
}
// 数值不同或者状态不同就更新
valueUpdated = (valueToUpdate->value != propValue->value ||
valueToUpdate->status != propValue->status);
} else if (!updateStatus) {
propValue->status = VehiclePropertyStatus::AVAILABLE;
}
// 把值存储在 values 里面
record->values[recId] = std::move(propValue);
// eventMode 为 EventMode::ON_VALUE_CHANGE
if (eventMode == EventMode::NEVER) {
return {};
}
updatedValue = *(record->values[recId]);
onValuesChangeCallback = mOnValuesChangeCallback;
onValueChangeCallback = mOnValueChangeCallback;
}
// callback 为空 直接返回
if (onValuesChangeCallback == nullptr && onValueChangeCallback == nullptr) {
// No callback registered.
return {};
}
// 通知 callback
if (eventMode == EventMode::ALWAYS || valueUpdated) {
if (onValuesChangeCallback != nullptr) {
onValuesChangeCallback({updatedValue});
} else {
onValueChangeCallback(updatedValue);
}
}
return {};
}
接收 IVehicleBus 数据
cpp
// 构造函数
EmulatedVehicleHardware::EmulatedVehicleHardware() {
Init();
}
// init 的方法
void EmulatedVehicleHardware::Init() {
mInQemu = isInQemu();
ALOGD("mInQemu=%s", mInQemu ? "true" : "false");
// 创建 VehicleBusCallback
mVehicleBusCallback = ::ndk::SharedRefBase::make<VehicleBusCallback>(this);
// 创建 VehicleEmulator 对象
mEmulator = std::make_unique<VehicleEmulator>(this);
startVehicleBuses();
}
class VehicleBusCallback : public BnVehicleBusCallback {
public:
VehicleBusCallback(
EmulatedVehicleHardware* vehicleHardware) :
mVehicleHardware(vehicleHardware) {}
// 有新的属性变化会回调
ndk::ScopedAStatus onNewPropValues(
const std::vector<AidlVehiclePropValue>& propValues) override;
private:
EmulatedVehicleHardware* mVehicleHardware;
};
// VehicleEmulator 构造函数
VehicleEmulator::VehicleEmulator(EmulatedVehicleHardware* hal) : mHal(hal) {
ALOGI("Starting SocketComm");
mSocketComm = std::make_unique<SocketComm>(this);
mSocketComm->start();
if (hal->isInQemu()) {
ALOGI("Starting PipeComm");
mPipeComm = std::make_unique<PipeComm>(this);
mPipeComm->start();
}
}
// IVehicleBus 接口模拟车辆总线的数据传输,支持发送和接收车辆属性数据。
// 提供回调机制,允许监听车辆属性的变化。
// 在仿真环境中测试车辆相关功能,无需实际的车辆硬件。
void EmulatedVehicleHardware::startVehicleBuses() {
std::vector<std::string> names;
AServiceManager_forEachDeclaredInstance(IVehicleBus::descriptor, static_cast<void*>(&names),
[](const char* instance, void* context) {
auto fullName = std::string(IVehicleBus::descriptor) + "/" + instance;
static_cast<std::vector<std::string>*>(context)->push_back(fullName);
});
// 获取 IVehicleBus 服务
for (const auto& fullName : names) {
::ndk::SpAIBinder binder(AServiceManager_waitForService(fullName.c_str()));
if (binder.get() == nullptr) {
ALOGE("%s binder returned null", fullName.c_str());
continue;
}
std::shared_ptr<IVehicleBus> vehicleBus = IVehicleBus::fromBinder(binder);
if (vehicleBus == nullptr) {
ALOGE("Couldn't open %s", fullName.c_str());
continue;
}
// 把 mVehicleBusCallback 添加到 IVehicleBus ,属性变化会回调
vehicleBus->setOnNewPropValuesCallback(mVehicleBusCallback);
mVehicleBuses.push_back(vehicleBus);
}
}
IVehicle binder 服务接口
aidl
package android.hardware.automotive.vehicle;
@VintfStability
interface IVehicle {
android.hardware.automotive.vehicle.VehiclePropConfigs getAllPropConfigs();
android.hardware.automotive.vehicle.VehiclePropConfigs getPropConfigs(in int[] props);
void getValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.GetValueRequests requests);
void setValues(android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SetValueRequests requests);
void subscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in android.hardware.automotive.vehicle.SubscribeOptions[] options, int maxSharedMemoryFileCount);
void unsubscribe(in android.hardware.automotive.vehicle.IVehicleCallback callback, in int[] propIds);
void returnSharedMemory(in android.hardware.automotive.vehicle.IVehicleCallback callback, long sharedMemoryId);
const long INVALID_MEMORY_ID = 0;
const int MAX_SHARED_MEMORY_FILES_PER_CLIENT = 3;
}
cpp
// DefaultVehicleHal 构造函数 ,IVehicle stub 实现类
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
: DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0){};
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
int32_t testInterfaceVersion)
: mVehicleHardware(std::move(vehicleHardware)),
// 创建 PendingRequestPool
mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
mTestInterfaceVersion(testInterfaceVersion) {
ALOGD("DefaultVehicleHal init");
IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get();
mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr);
// mEventBatchingWindow 为 0
mEventBatchingWindow = mVehicleHardware->getPropertyOnChangeEventBatchingWindow();
if (mEventBatchingWindow != std::chrono::nanoseconds(0)) {
mBatchedEventQueue = std::make_shared<ConcurrentQueue<VehiclePropValue>>();
mPropertyChangeEventsBatchingConsumer =
std::make_shared<BatchingConsumer<VehiclePropValue>>();
mPropertyChangeEventsBatchingConsumer->run(
mBatchedEventQueue.get(), mEventBatchingWindow,
[this](std::vector<VehiclePropValue> batchedEvents) {
handleBatchedPropertyEvents(std::move(batchedEvents));
});
}
std::weak_ptr<ConcurrentQueue<VehiclePropValue>> batchedEventQueueCopy = mBatchedEventQueue;
std::chrono::nanoseconds eventBatchingWindow = mEventBatchingWindow;
std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager;
// 注册属性变化事件
mVehicleHardware->registerOnPropertyChangeEvent(
std::make_unique<IVehicleHardware::PropertyChangeCallback>(
[subscriptionManagerCopy, batchedEventQueueCopy,
eventBatchingWindow](std::vector<VehiclePropValue> updatedValues) {
if (eventBatchingWindow != std::chrono::nanoseconds(0)) {
batchPropertyChangeEvent(batchedEventQueueCopy,
std::move(updatedValues));
} else {
onPropertyChangeEvent(subscriptionManagerCopy,
std::move(updatedValues));
}
}));
// 注册属性错误事件
mVehicleHardware->registerOnPropertySetErrorEvent(
std::make_unique<IVehicleHardware::PropertySetErrorCallback>(
[subscriptionManagerCopy](std::vector<SetValueErrorEvent> errorEvents) {
onPropertySetErrorEvent(subscriptionManagerCopy, errorEvents);
}));
// 发送心跳信号,以监控 VHAL 的健康状态
mRecurrentAction = std::make_shared<std::function<void()>>(
[vehicleHardwarePtr, subscriptionManagerCopy]() {
checkHealth(vehicleHardwarePtr, subscriptionManagerCopy);
});
// 注册心跳回调
mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction);
mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>();
mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); });
// 注册 binder 死亡回调
mDeathRecipient = ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied));
AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
&DefaultVehicleHal::onBinderUnlinked);
}