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);
}
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui