Vehicle HAL 介绍

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_SETFUEL_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);
}
相关推荐
___波子 Pro Max.1 小时前
Android envsetup与Python venv使用指南
android·python
武帝为此1 小时前
【MySQL 删除数据详解】
android·数据库·mysql
顾林海2 小时前
深度解析HashMap工作原理
android·java·面试
V少年2 小时前
深入浅出DiskLruCache原理
android
鱼洗竹2 小时前
协程的挂起与恢复
android
清风~徐~来3 小时前
【Linux】进程创建、进程终止、进程等待
android·linux·运维
百锦再4 小时前
Android游戏辅助工具开发详解
android·游戏·模拟·识别·辅助·外挂
QING6184 小时前
Kotlin 类型转换与超类 Any 详解
android·kotlin·app
QING6185 小时前
一文带你了解 Kotlin infix 函数的基本用法和使用场景
android·kotlin·app
张风捷特烈5 小时前
平面上的三维空间#04 | 万物之母 - 三角形
android·flutter·canvas