跳转至

Android-S Vehicle HAL架构

VehicleHAL 简介

  • 源码位置 : hardware/interfaces/automotive/vehicle/2.0/

  • VehicleHAL 类图

接口文件

  • types.hal 定义的是一些数据结构
  • IVehicle.hal 定义的是从 CarService 往 HAL 调用的接口
  • IVehicleCallback.hal 则是 HAL 往 CarService 上报回调的接口

2. VehicleHal初始化流程

初始化从执行 hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp 的main函数开始:

  • 创建 VehiclePropertyStore 对象
  • 创建 EmulatedVehicleConnector 对象
  • 创建 EmulatedUserHal 对象
  • 创建 EmulatedVehicleHal 对象
  • 创建 VehicleEmulator 对象
  • 创建 VehicleHalManager 对象
hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp

int main(int /* argc */, char* /* argv */ []) {
    //1.  创建一个 VehiclePropertyStore 对象,并使用std::make_unique进行智能指针的初始化
    auto store = std::make_unique<VehiclePropertyStore>();
    //2. 创建一个 EmulatedVehicleConnector 对象,并使用std::make_unique进行智能指针的初始化
    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
    // 载入配置声明
    connector->LoadConfigDeclarations(impl::kVehicleProperties);
    //3. 获取 EmulatedUserHal 对象
    auto userHal = connector->getEmulatedUserHal();
    //4. 创建一个 EmulatedVehicleHal 对象,并使用std::make_unique进行智能指针的初始化
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
    //5. 创建一个 VehicleEmulator 对象,并使用std::make_unique进行智能指针的初始化
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    // 创建一个 VehicleHalManager 对象,并使用std::make_unique进行智能指针的初始化
    auto service = std::make_unique<VehicleHalManager>(hal.get());
    // 设置connector的value pool
    connector->setValuePool(hal->getValuePool());
    // 配置RPC线程池
    configureRpcThreadpool(4, true /* callerWillJoin */);

    ALOGI("Registering as service...");
    // 注册为服务
    status_t status = service->registerAsService();

    if (status != OK) {
        ALOGE("Unable to register vehicle service (%d)", status);
        return 1;
    }

    ALOGI("Ready");
    // 加入RPC线程池
    joinRpcThreadpool();

    return 1;
}

VehiclePropertyStore

VehiclePropertyStore的类,用于存储和访问车辆属性的配置和值。

  • registerProperty:注册车辆属性的配置。
  • writeValue:存储提供的属性值。
  • removeValue:删除指定的属性值。
  • removeValuesForProperty:删除指定属性的所有值。
  • readAllValues:读取所有属性的值。
  • readValuesForProperty:读取指定属性的所有值。
  • readValueOrNull:根据请求读取属性值,如果不存在则返回空指针。
  • getConfigOrNull:根据属性ID获取属性配置,如果不存在则返回空指针。
  • getConfigOrDie:根据属性ID获取属性配置,如果不存在则抛出异常。
hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h

class VehiclePropertyStore {

public:
    void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr);

    /* Stores provided value. Returns true if value was written returns false if config for
     * example wasn't registered. */
    bool writeValue(const VehiclePropValue& propValue, bool updateStatus);

    void removeValue(const VehiclePropValue& propValue);
    void removeValuesForProperty(int32_t propId);

    std::vector<VehiclePropValue> readAllValues() const;
    std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const;
    std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const;
    std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0,
                                                      int64_t token = 0) const;

    std::vector<VehiclePropConfig> getAllConfigs() const;
    const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
    const VehiclePropConfig* getConfigOrDie(int32_t propId) const;

    ...

};

EmulatedVehicleConnector

EmulatedVehicleConnector 继承自 IPassThroughConnector,是Android汽车HAL(Hardware Abstraction Layer)的一部分,用于模拟车辆连接器。

该代码的功能是实现了一个模拟车辆连接器,用于处理车辆属性的设置和转储请求,并与 EmulatedUserHal 进行交互。

  • getEmulatedUserHal() 的函数,返回一个 EmulatedUserHal 类型的指针。
  • 实现了 VehicleHalServer 接口中的 triggerSendAllValues() 函数。用于触发将所有值发送给客户端。
  • 实现了 VehicleHalServer 接口中的 onSetProperty() 函数。用于处理设置属性的请求,如果属性由 EmulatedUserHal 支持,则调用 EmulatedUserHal 的 onSetProperty() 函数进行处理,并根据返回值更新属性的值。
  • 实现了 VehicleHalServer 接口中的 onDump() 函数。
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h

class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
  public:
    EmulatedVehicleConnector() = default;

    EmulatedUserHal* getEmulatedUserHal();

    // Methods from VehicleHalServer
    void triggerSendAllValues() override;

    StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;

    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;

  private:
    EmulatedUserHal mEmulatedUserHal;
};

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
...

VehicleHalServer::LoadConfigDeclarations()

我们在 EmulatedVehicleConnector 里并没有看到 LoadConfigDeclarations() 函数,那么是在哪里呢?

hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp

auto connector = std::make_unique<impl::EmulatedVehicleConnector>();  
connector->LoadConfigDeclarations(impl::kVehicleProperties);

前面什么提到过 EmulatedVehicleConnector 继承自 IPassThroughConnector

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h

class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
}

果然,我们在 VehicleHalServer 里找到函数 LoadConfigDeclarations()

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h

class VehicleHalServer : public IVehicleServer {
    void LoadConfigDeclarations(const std::vector<ConfigDeclaration> additionalProperties);
}

把 hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h 里声明的 kVehicleProperties 配置全部加载。

EmulatedUserHal

EmulatedUserHal 用于模拟用户 HAL 的行为,通过使用 lshal 调试请求来实现。

  • isSupported():检查模拟器是否支持给定的属性。
  • onSetProperty():允许模拟器设置属性,并返回更新后的属性和状态码。
  • onGetProperty():从模拟器获取属性值,并返回属性值和状态码。
  • dump():lshal 命令 dump
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp

EmulatedVehicleHal

EmulatedVehicleHal 类是 EmulatedVehicleHalIface、VehicleHal 的实现 用于连接到模拟器而不是真实的车辆网络。

  • initStaticConfig() : 用于初始化静态配置。
  • 实现 VehicleHal 接口的方法 : onCreate()、listProperties()、get()、set()、subscribe()、unsubscribe() 和 dump()。
  • 实现 EmulatedVehicleHalIface 接口的方法 : setPropertyFromVehicle()、getAllProperties() 和 getAllPropertiesOverride()。
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
class EmulatedVehicleHalIface : public VehicleHal {
}


hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h

/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
class EmulatedVehicleHal : public EmulatedVehicleHalIface {
public:
    EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
                       EmulatedUserHal* emulatedUserHal = nullptr);

    //  Methods from VehicleHal
    void onCreate() override;
    std::vector<VehiclePropConfig> listProperties() override;
    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
                            StatusCode* outStatus) override;
    StatusCode set(const VehiclePropValue& propValue) override;
    StatusCode subscribe(int32_t property, float sampleRate) override;
    StatusCode unsubscribe(int32_t property) override;
    bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;

    //  Methods from EmulatedVehicleHalIface
    bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
    std::vector<VehiclePropValue> getAllProperties() const override;
    void getAllPropertiesOverride();

private:

    VehiclePropertyStore* mPropStore;
    VehicleHalClient* mVehicleClient;
    EmulatedUserHal* mEmulatedUserHal;
};

VehicleEmulator

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h

class VehicleEmulator : public MessageProcessor {
   public:
    VehicleEmulator(EmulatedVehicleHalIface* hal);

private:
    EmulatedVehicleHalIface* mHal;
    std::unique_ptr<SocketComm> mSocketComm;
    std::unique_ptr<PipeComm> mPipeComm;
};


hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp

VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} {
    mHal->registerEmulator(this);

    ALOGI("Starting SocketComm");
    mSocketComm = std::make_unique<SocketComm>(this);
    mSocketComm->start();

    if (isInEmulator()) {
        ALOGI("Starting PipeComm");
        mPipeComm = std::make_unique<PipeComm>(this);
        mPipeComm->start();
    }
}

VehicleHalManager

  • 重置 HidlVecOfVehiclePropValuePool HIDL属性对象池大小
  • 开启事件消费着队列
  • VehicleHal 初始化
hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h

class VehicleHalManager : public IVehicle {
public:
    VehicleHalManager(VehicleHal* vehicleHal)
        : mHal(vehicleHal),
         // 1. mSubscriptionManager成员变量被初始化为一个绑定到onAllClientsUnsubscribed方法的函数对象。
         // 该函数对象使用std::bind绑定了this指针和std::placeholders::_1占位符。
          mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
                                         this, std::placeholders::_1)) {
        init();
    }

    ...
}


hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp

void VehicleHalManager::init() {
    ALOGI("VehicleHalManager::init");

    // 调整 mHidlVecOfVehiclePropValuePool 的大小为 20
    // constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);

    // 开启事件消费着队列
    mBatchingConsumer.run(&mEventQueue, // 启动批处理消费者线程
                          kHalEventBatchingTimeWindow, // 批处理时间窗口
                          std::bind(&VehicleHalManager::onBatchHalEvent, // 绑定 onBatchHalEvent 函数
                                    this, _1));

    // 初始化 VehicleHal
    mHal->init(&mValueObjectPool,
               std::bind(&VehicleHalManager::onHalEvent, this, _1), // 绑定 onHalEvent 函数
               std::bind(&VehicleHalManager::onHalPropertySetError, this, // 绑定 onHalPropertySetError 函数
                         _1, _2, _3));

    // 初始化从 VehicleHal 收到的 vehicle 属性的索引
    auto supportedPropConfigs = mHal->listProperties(); // 获取支持的属性配置列表
    mConfigIndex.reset(new VehiclePropConfigIndex(supportedPropConfigs)); // 使用支持的属性配置列表创建VehiclePropConfigIndex对象

    std::vector<int32_t> supportedProperties( // 创建支持的属性列表
        supportedPropConfigs.size());
    for (const auto& config : supportedPropConfigs) {
        supportedProperties.push_back(config.prop); // 将支持的属性添加到列表中
    }
}

VehicleHal.init()

VehicleHal.h 初始化做了以下操作: - 初始化 mValuePool - 初始化 mOnHalEvent - 初始化 mOnHalPropertySetError 变量 - 调用 onCreate()

hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h

class VehicleHal {

    ...

    /**  
    * Override this method if you need to do one-time initialization.  
    */  
    virtual void onCreate() {}

    void init(
        VehiclePropValuePool* valueObjectPool,
        const HalEventFunction& onHalEvent,
        const HalErrorFunction& onHalError) {
        mValuePool = valueObjectPool;
        mOnHalEvent = onHalEvent;
        mOnHalPropertySetError = onHalError;

        onCreate();
    }

    ...

}

调用 onCreate() 函数,遍历属性列表并以 mPropStore,即 VehiclePropertyStore 保存当前值

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
class EmulatedVehicleHalIface : public VehicleHal {
}

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
class EmulatedVehicleHal : public EmulatedVehicleHalIface {
    // Methods from VehicleHal  
    void onCreate() override;
}

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
// 解析支持的属性列表并生成包含当前值的属性值向量。 
void EmulatedVehicleHal::onCreate() {
    ...
}

VehicleHal启动序列图


sequenceDiagram

VehicleService ->> VehicleService:main()
    Note over VehicleService : 进程主入口,初始化 VehicleHal 等,并注册服务

VehicleService ->> VehiclePropertyStore:EmulatedVehicleHal() 
Note over VehiclePropertyStore : 并使用 std::make_unique 进行智能指针的初始化,并返回对象 store

VehicleService ->> EmulatedVehicleConnector:EmulatedVehicleConnector()
Note over EmulatedVehicleConnector : 并使用 std::make_unique 进行智能指针的初始化,并返回对象 connector

VehicleService ->> EmulatedVehicleHal:EmulatedVehicleHal()
Note over EmulatedVehicleHal : 并使用 std::make_unique 进行智能指针的初始化,构造函数传入VehiclePropertyStore、VehicleHalClient、EmulatedUserHal,并返回对象 hal

VehicleService ->> VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal)
Note over VehicleEmulator : 并使用 std::make_unique 进行智能指针的初始化,构造函数传入EmulatedVehicleHalIface,并返回对象 emulator

VehicleService ->> VehicleHalManager::VehicleHalManager(VehicleHal* vehicleHal)
Note over VehicleHalManager : 并使用 std::make_unique 进行智能指针的初始化,VehicleHal,并返回对象 service

types.hal

VehiclePropertyType

车辆属性类型

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 枚举支持的车辆属性数据类型。
 * 
 * 用于在VehicleProperty枚举中创建属性ID。
 */
enum VehiclePropertyType : int32_t {
    STRING          = 0x00100000, // 字符串类型,1048576
    BOOLEAN         = 0x00200000, // 布尔类型,2097152
    INT32           = 0x00400000, // 32位整数类型,4194304
    INT32_VEC       = 0x00410000, // 32位整数向量类型,4259840
    INT64           = 0x00500000, // 64位整数类型,5242880
    INT64_VEC       = 0x00510000, // 64位整数向量类型,5308416
    FLOAT           = 0x00600000, // 浮点数类型,6291456
    FLOAT_VEC       = 0x00610000, // 浮点数向量类型,6356992
    BYTES           = 0x00700000, // 字节类型,7340032

    /**     
     * 标量或向量类型的任意组合。具体格式必须在属性的描述中提供。
     *     
     * 对于供应商的混合类型属性,configArray需要按照以下结构进行格式化。
     *      
     * configArray[0],1表示属性具有字符串值
     * configArray[1],1表示属性具有布尔值。
     * configArray[2],1表示属性具有整数值。
     * configArray[3],数字表示属性中整数数组的大小。
     * configArray[4],1表示属性具有长整数值。
     * configArray[5],数字表示属性中长整数数组的大小。
     * configArray[6],1表示属性具有浮点数值。
     * configArray[7],数字表示属性中浮点数数组的大小。
     * configArray[8],数字表示属性中字节数组的大小。
     * 例如:
     * {@code configArray = {1, 1, 1, 3, 0, 0, 0, 0, 0}} 表示属性具有
     * 字符串值、布尔值、整数值和一个包含3个整数的数组。
     */
    MIXED           = 0x00e00000, // 混合类型,14680064

    MASK            = 0x00ff0000 // 属性类型掩码,16711680
};

VehicleArea

车辆区域类型

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 车辆区域
 * 用于构建 VehicleProperty 枚举中的属性ID。
 *
 * 一些属性可能与特定的车辆区域相关联。例如,VehicleProperty:DOOR_LOCK 属性必须与特定的车门相关联,
 * 因此该属性必须标记为 VehicleArea:DOOR 标志。
 *
 * 其他属性可能与特定的车辆区域无关。这些属性必须具有 VehicleArea:GLOBAL 标志。
 *
 * [定义] 区域:区域表示 AreaType 的一个唯一元素。例如,如果 AreaType 是 WINDOW ,则一个区域可以是 FRONT_WINDSHIELD 。
 *
 * [定义] 区域ID:区域ID 是一个或多个区域的组合,使用 Area 枚举的位掩码表示。不同的 AreaType 不能在一个单独的 AreaID 中混合。
 * 例如,窗口区域不能与座位区域组合在一个 AreaID 中。
 *
 * 映射分区属性到区域ID 的规则:
 *  - 属性必须映射到一个在属性值更改时受影响的 AreaID 数组。
 *  - 数组中的每个元素必须表示一个 AreaID ,在该 AreaID 中,属性值只能在 AreaID 中的所有区域中同时更改,而不能独立更改。
 *    也就是说,当属性值在数组中的一个区域中更改时,它必须自动在 AreaID 中的所有其他区域中更改。
 *  - 属性值必须在数组中的任意两个不同的 AreaID 中独立可控。
 *  - 区域在 AreaID 数组中只能出现一次。也就是说,一个区域只能是 AreaID 数组中的一个区域。
 *
 * [定义] 全局属性:适用于整个车辆并且不与特定区域相关联的属性。例如,FUEL_LEVEL,HVAC_STEERING_WHEEL_HEAT。
 *
 * 映射全局属性到区域ID 的规则:
 *  - 全局属性不得映射到区域ID。
*/
enum VehicleArea : int32_t {
    GLOBAL      = 0x01000000, // 16777216
    WINDOW      = 0x03000000, // WINDOW映射到VehicleAreaWindow枚举,50331648
    MIRROR      = 0x04000000, // MIRROR映射到VehicleAreaMirror枚举,67108864
    SEAT        = 0x05000000, // SEAT映射到VehicleAreaSeat枚举,83886080
    DOOR        = 0x06000000, // DOOR映射到VehicleAreaDoor枚举,100663296
    WHEEL       = 0x07000000, // WHEEL映射到VehicleAreaWheel枚举,117440512

    MASK        = 0x0f000000, //251658240
};

VehiclePropertyGroup

车辆属性分组类型

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 定义了属性组的枚举类型。
 *
 * 用于在VehicleProperty枚举中创建属性ID。
 */
enum VehiclePropertyGroup : int32_t {
    /**
     * 
     */
    SYSTEM      = 0x10000000, // 在AOSP中声明的属性必须使用此标志, 268435456

    /**
     * 
     */
    VENDOR      = 0x20000000, // 由供应商声明的属性必须使用此标志, 536870912

    MASK        = 0xf0000000, // -268435456 ?
};

VehicleAreaWindow

车辆窗户区域属性

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 定义了车辆中的各种挡风玻璃/窗户。
 */
enum VehicleAreaWindow : int32_t {
    FRONT_WINDSHIELD  = 0x00000001,  // 前挡风玻璃,1
    REAR_WINDSHIELD   = 0x00000002,  // 后挡风玻璃,2
    ROW_1_LEFT        = 0x00000010,  // 第一排左侧窗户,16
    ROW_1_RIGHT       = 0x00000040,  // 第一排右侧窗户,64
    ROW_2_LEFT        = 0x00000100,  // 第二排左侧窗户,256
    ROW_2_RIGHT       = 0x00000400,  // 第二排右侧窗户,1024
    ROW_3_LEFT        = 0x00001000,  // 第三排左侧窗户,4096
    ROW_3_RIGHT       = 0x00004000,  // 第三排右侧窗户,16384

    ROOF_TOP_1        = 0x00010000,  // 顶部1号窗户,65536
    ROOF_TOP_2        = 0x00020000,  // 顶部2号窗户,131072
};

VehiclePropertyAccess

车辆属性访问权限

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * Property config 定义了它的功能。API的用户必须首先获取 property config,
 * 以了解 get() 命令的输出,并确保 set() 或 events 命令与预期输出同步。
 */
enum VehiclePropertyAccess : int32_t {
    NONE = 0x00, // 没有访问权限,0
    READ = 0x01, // 只读权限,1
    WRITE = 0x02, // 只写权限,2
    READ_WRITE = 0x03, // 读写权限,3
};

VehiclePropertyChangeMode

车辆属性变化模式

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 描述属性值如何变化的枚举类型
 */
enum VehiclePropertyChangeMode : int32_t {
    /**     
     * 此类型的属性不能被更改。不支持对这些属性进行 subscribe 订阅。只能 IVehicle.get() 获取
     */
    STATIC = 0x00,

    /**
     * ON_CHANGE 这个类型的属性当变化时必须上报
     * 此类型的属性在发生变化时必须报告。 IVehicle.get() 调用必须返回当前值。
     * 对于此属性的设置操作被假定为异步的。当在 IVehicle.set() 之后读取属性(使用 IVehicle.get() )时,
     * 它可能仍然返回旧值,直到支持此属性的底层硬件实际上改变了状态。一旦状态改变,属性必须作为事件分发已更改的值。
     */
    ON_CHANGE = 0x01,

    /**
     * 此类型的属性连续变化,并且需要固定的采样率来检索数据。实现者可以选择在重要的值变化时发送额外的通知。
     */
    CONTINUOUS = 0x02,
};

SubscribeOptions

车辆属性事件订阅信息

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 封装了有关订阅车辆属性事件的信息。
 */
struct SubscribeOptions {
    /** 要订阅的属性 */
    int32_t propId;

    /**
     * 采样率,以赫兹(Hz)为单位。
     *
     * 对于具有 VehiclePropertyChangeMode::CONTINUOUS 的属性,必须提供。
     * 该值必须在给定属性的 VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate 范围内。
     * 此值表示客户端希望每秒接收多少次更新。
     */
    float sampleRate;

    /** 指示要监听哪些事件源的标志。 */
    SubscribeFlags flags;
};

enum SubscribeFlags : int32_t {
    UNDEFINED = 0x0,

    /**
     * 订阅来自车辆HAL的事件
     * (很可能是车辆本身产生的事件)。
     */
    EVENTS_FROM_CAR = 0x1,

    /**
     * 使用此标志订阅当车辆HAL的客户端(例如Car Service)调用 IVehicle.set(...) 时的事件。
     */
    EVENTS_FROM_ANDROID = 0x2,
};

VehicleAreaSeat

车辆座椅属性

hardware/interfaces/automotive/vehicle/2.0/types.hal

/**
 * 不同的车辆座位。
 */
enum VehicleAreaSeat : int32_t {
    ROW_1_LEFT   = 0x0001,   // 第一排左侧座位, 1
    ROW_1_CENTER = 0x0002,   // 第一排中间座位, 2
    ROW_1_RIGHT  = 0x0004,   // 第一排右侧座位, 4
    ROW_2_LEFT   = 0x0010,   // 第二排左侧座位, 16
    ROW_2_CENTER = 0x0020,   // 第二排中间座位, 32
    ROW_2_RIGHT  = 0x0040,   // 第二排右侧座位, 64
    ROW_3_LEFT   = 0x0100,   // 第三排左侧座位, 256
    ROW_3_CENTER = 0x0200,   // 第三排中间座位, 512
    ROW_3_RIGHT  = 0x0400    // 第三排右侧座位, 1024
};

StatusCode

接口调用状态值

hardware/interfaces/automotive/vehicle/2.0/types.hal

/** 
 * 车辆HAL接口中使用的错误代码。
 */
enum StatusCode : int32_t {
    OK = 0,

    // 再试一次
    TRY_AGAIN = 1,

    // 提供的参数无效
    INVALID_ARG = 2,

    // 当与车辆属性关联的设备不可用时,必须返回此代码。例如,当客户端尝试在整个HVAC单元关闭时设置HVAC温度。     
    NOT_AVAILABLE = 3,

    // 访问被拒绝
    ACCESS_DENIED = 4,

    // 在车辆HAL中发生了意外情况
    INTERNAL_ERROR = 5,
};

IVehicle.hal

hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal

interface IVehicle {
  /**
   * 返回此车辆HAL支持的所有属性配置的列表。
   */
  getAllPropConfigs() generates (vec<VehiclePropConfig> propConfigs);

  /**
   * 返回给定属性的属性配置列表。
   *
   * 如果未找到请求的 VehicleProperty ,则必须返回 StatusCode::INVALID_ARG,
   * 否则返回带有 StatusCode::OK 的车辆属性配置列表。
   */
  getPropConfigs(vec<int32_t> props)
          generates (StatusCode status, vec<VehiclePropConfig> propConfigs);

  /**
   * 获取车辆属性值。
   *
   * 对于 VehiclePropertyChangeMode::STATIC 属性,此方法必须始终返回相同的值。
   * 对于 VehiclePropertyChangeMode::ON_CHANGE 属性,它必须返回最新可用的值。
   *
   * 一些属性(如 RADIO_PRESET )需要在GET请求中传递 VehiclePropValue 对象中的附加数据。
   *
   * 如果尚无可用数据,即在初始阶段可能发生的情况下,此调用必须立即返回 StatusCode::TRY_AGAIN 的错误代码。
   */
  get(VehiclePropValue requestedPropValue)
          generates (StatusCode status, VehiclePropValue propValue);

  /**
   * 设置车辆属性值。
   *
   * 忽略数据的时间戳。
   *
   * 设置某些属性需要有初始状态可用。如果初始数据尚不可用,则此调用必须返回 StatusCode::TRY_AGAIN。
   * 对于具有单独电源控制的属性,如果未启动属性,则此调用必须返回 StatusCode::NOT_AVAILABLE错误。
   */
  set(VehiclePropValue propValue) generates (StatusCode status);

  /**
   * 订阅属性事件。
   *
   * 客户端必须能够根据选项参数中提供的数据订阅多个属性。
   *
   * @param listener 此客户端必须在适当的事件上被调用。
   * @param options 订阅的选项列表。SubscribeOption包含诸如属性Id、区域Id、采样率等信息。
   */
  subscribe(IVehicleCallback callback, vec<SubscribeOptions> options)
          generates (StatusCode status);

  /**
   * 取消订阅属性事件。
   *
   * 如果此客户端未订阅给定属性,则此方法必须返回StatusCode::INVALID_ARG。
   */
  unsubscribe(IVehicleCallback callback, int32_t propId)
          generates (StatusCode status);

  /**
   * 打印车辆HAL的调试状态。
   */
  debugDump() generates (string s);
};

IVehicleCallback.hal

hardware/interfaces/automotive/vehicle/2.0/IVehicleCallback.hal

interface IVehicleCallback {

    /**
     * 当API用户订阅的变量需要报告时,会触发此事件回调。这可能是基于阈值和频率(常规订阅,参见subscribe调用的参数),
     * 或者当调用 IVehicle.set() 方法并且需要报告实际更改时。
     *
     * 这些回调是分块的。
     *
     * @param values 更新的值。
     */
    oneway onPropertyEvent(vec<VehiclePropValue> propValues);

    /**
     * 如果客户端使用 SubscribeFlags::EVENTS_FROM_ANDROID 标志订阅了属性,并且调用了 IVehicle.set(...) 方法,
     * 则会调用此方法。
     *
     * 这些事件必须立即传递给订阅者,不进行任何批处理。
     *
     * @param value 客户端设置的值。
     */
    oneway onPropertySet(VehiclePropValue propValue);

    /**
     * 设置属性值通常是异步操作。因此,即使客户端从IVehicle::set(...)收到StatusCode::OK,
     * 这也不能保证该值已成功传播到车辆网络。如果发生这种罕见的事件,必须调用此方法。
     *
     * @param errorCode - StatusCode枚举中的任何值。
     * @param property - 发生错误的属性。
     * @param areaId - 指定发生问题的区域的位掩码,对于全局属性必须为0。
     */
    oneway onPropertySetError(StatusCode errorCode,
                              int32_t propId,
                              int32_t areaId);
};

VehicleHal 获取(设置)属性

subscribe订阅属性

CarService.onCreate()

CarService 在 onCreate() 中创建 ICarImpl

packages/services/Car/service/src/com/android/car/CarService.java

@Override
public void onCreate() {
    ...

    mVehicle = getVehicle();

    mICarImpl = new ICarImpl(this,
            mVehicle,
            SystemInterface.Builder.defaultSystemInterface(this).build(),
            mVehicleInterfaceName);
    mICarImpl.init();

    ...
}

创建 ICarImpl 的时候传了 mVehicle 进去,也就是 IVehicle 。

packages/services/Car/service/src/com/android/car/CarService.java

@Nullable
private static IVehicle getVehicle() {
    final String instanceName = SystemProperties.get("ro.vehicle.hal", "default");

    try {
        return android.hardware.automotive.vehicle.V2_0.IVehicle.getService(instanceName);
    } catch (RemoteException e) {
        Slog.e(CarLog.TAG_SERVICE, "Failed to get IVehicle/" + instanceName + " service", e);
    } catch (NoSuchElementException e) {
        Slog.e(CarLog.TAG_SERVICE, "IVehicle/" + instanceName + " service not registered yet");
    }
    return null;
}

好家伙,就是 VehicleHAl 服务。

ICarImpl构造函数

构造函数中 new VehicleHal 对象,然后又在 CarImpl 的 init() 函数中调用 VehicleHal 对象的 init() 函数

packages/services/Car/service/src/com/android/car/ICarImpl.java

public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
        String vehicleInterfaceName) {
    this(serviceContext, vehicle, systemInterface, vehicleInterfaceName,
            /* carUserService= */ null, /* carWatchdogService= */ null,
            /* powerPolicyDaemon= */ null);
}

@VisibleForTesting
ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
        String vehicleInterfaceName,
        @Nullable CarUserService carUserService,
        @Nullable CarWatchdogService carWatchdogService,
        @Nullable ICarPowerPolicySystemNotification powerPolicyDaemon) {

    ...

    mHal = constructWithTrace(t, VehicleHal.class,
            () -> new VehicleHal(serviceContext, vehicle));

    ...
}

@MainThread
void init() {
    ...
    mHal.init();
    ...
}

VehicleHal

构造函数new各个HalService(继承于 HalServiceBase ),并且 new HalClient 客户端对象。

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public VehicleHal(Context context, IVehicle vehicle) {
    mHandlerThread = CarServiceUtils.getHandlerThread(
            VehicleHal.class.getSimpleName());
    mHandler = new Handler(mHandlerThread.getLooper());
    mPowerHal = new PowerHalService(this);
    mPropertyHal = new PropertyHalService(this);
    mInputHal = new InputHalService(this);
    mVmsHal = new VmsHalService(context, this);
    mUserHal = new UserHalService(this);
    mDiagnosticHal = new DiagnosticHalService(this);
    mClusterHalService = new ClusterHalService(this);
    mEvsHal = new EvsHalService(this);
    mTimeHalService = new TimeHalService(context, this);
    //TODO(b/202396546): Dedupe this assignment with the other one in constructor below
    mAllServices.addAll(Arrays.asList(mPowerHal,
            mInputHal,
            mDiagnosticHal,
            mVmsHal,
            mUserHal,
            mClusterHalService,
            mEvsHal,
            mTimeHalService,
            mPropertyHal)); // mPropertyHal should be the last.
    mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(),
            /* callback= */ this);
}
getAllPropConfigs()

mHalClient.getAllPropConfigs() 从 Vehicle HAL(IVehicle.hal) 获取所有的属性。 调用到VehicleHalManager.cpp 的 getAllPropConfigs() 函数。

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public void init() {
    fetchAllPropConfigs();

    ...
}

private void fetchAllPropConfigs() {
    synchronized (mLock) {
        if (!mAllProperties.isEmpty()) { // already set
            Slog.i(CarLog.TAG_HAL, "fetchAllPropConfigs already fetched");
            return;
        }
    }
    ArrayList<VehiclePropConfig> configs;
    try {
        configs = mHalClient.getAllPropConfigs();
        if (configs == null || configs.size() == 0) {
            Slog.e(CarLog.TAG_HAL, "getAllPropConfigs returned empty configs");
            return;
        }
    } catch (RemoteException e) {
        throw new RuntimeException("Unable to retrieve vehicle property configuration", e);
    }

    synchronized (mLock) {
        // Create map of all properties
        for (VehiclePropConfig p : configs) {
            if (DBG) {
                Slog.i(CarLog.TAG_HAL, "Add config for prop:" + Integer.toHexString(p.prop)
                        + " config:" + p);
            }
            mAllProperties.put(p.prop, p);
        }
    }
}
VehicleHal.init()

在 init() 中调用 fetchAllPropConfigs() 获取到所有的属性,并保存在 mAllProperties 变量中。 接着还有一件很重要的事情是,给每个服务更新对应的属性。

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public void init() {
    fetchAllPropConfigs();

    // PropertyHalService will take most properties, so make it big enough.
    ArrayList<VehiclePropConfig> configsForService = new ArrayList<>(mAllServices.size());
    for (int i = 0; i < mAllServices.size(); i++) {
        HalServiceBase service = mAllServices.get(i);
        int[] supportedProps =  service.getAllSupportedProperties();
        configsForService.clear();
        synchronized (mLock) {
            if (supportedProps.length == 0) {
                for (Integer propId : mAllProperties.keySet()) {
                    if (service.isSupportedProperty(propId)) {
                        VehiclePropConfig config = mAllProperties.get(propId);
                        mPropertyHandlers.append(propId, service);
                        configsForService.add(config);
                    }
                }
            } else {
                for (int prop : supportedProps) {
                    VehiclePropConfig config = mAllProperties.get(prop);
                    if (config == null) {
                        continue;
                    }
                    mPropertyHandlers.append(prop, service);
                    configsForService.add(config);
                }
            }
        }
        service.takeProperties(configsForService);
        service.init();
    }
}

根据签名的构造函数,我们知道 mAllServices 就是各个 HalService,这里我们拿 PowerHalService 举例。

PowerHalService.getAllSupportedProperties()

PowerHalService支持的所有属性是: - AP_POWER_STATE_REQ - AP_POWER_STATE_REPORT - DISPLAY_BRIGHTNESS

packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

public class PowerHalService extends HalServiceBase {    

    private static final int[] SUPPORTED_PROPERTIES = new int[]{
            AP_POWER_STATE_REQ,
            AP_POWER_STATE_REPORT,
            DISPLAY_BRIGHTNESS
    };

    @Override
    public int[] getAllSupportedProperties() {
        return SUPPORTED_PROPERTIES;
    }

}

在回到前面的 init() 函数,从 PowerHalService.getAllSupportedProperties() 是有获取到支持属性的;所以接着从 mAllProperties 去寻找是否有配置,最后调用 PowerHalService.takeProperties(configsForService) 更新

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public void init() {
    ...

    // PropertyHalService will take most properties, so make it big enough.
    ArrayList<VehiclePropConfig> configsForService = new ArrayList<>(mAllServices.size());
    for (int i = 0; i < mAllServices.size(); i++) {
        HalServiceBase service = mAllServices.get(i);
        int[] supportedProps =  service.getAllSupportedProperties();//有属性
        configsForService.clear();
        synchronized (mLock) {
            if (supportedProps.length == 0) {//所以不进这里
                for (Integer propId : mAllProperties.keySet()) {
                    if (service.isSupportedProperty(propId)) {
                        VehiclePropConfig config = mAllProperties.get(propId);
                        mPropertyHandlers.append(propId, service);
                        configsForService.add(config);
                    }
                }
            } else {
                for (int prop : supportedProps) {
                    //从 hal 里查到是否有匹配的
                    VehiclePropConfig config = mAllProperties.get(prop);
                    if (config == null) {
                        continue;
                    }
                    // 有则添加到 configsForService 
                    mPropertyHandlers.append(prop, service);
                    configsForService.add(config);
                }
            }
        }

        service.takeProperties(configsForService);
        service.init();
    }
}

PowerHalService.takeProperties()

packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

public class PowerHalService extends HalServiceBase {

    @GuardedBy("mLock")
    private final HashMap<Integer, VehiclePropConfig> mProperties = new HashMap<>();

    @Override
    public void takeProperties(Collection<VehiclePropConfig> properties) {
        if (properties.isEmpty()) {
            return;
        }
        synchronized (mLock) {
            for (VehiclePropConfig config : properties) {
                mProperties.put(config.prop, config);
            }
        }
    }

}

PowerHalService.init()

调用 mHal.subscribeProperty(this, config.prop); 订阅属性。

packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

public class PowerHalService extends HalServiceBase {

    @Override
    public void init() {
        synchronized (mLock) {
            for (VehiclePropConfig config : mProperties.values()) {
                if (VehicleHal.isPropertySubscribable(config)) {
                    mHal.subscribeProperty(this, config.prop);
                }
            }
            VehiclePropConfig brightnessProperty = mProperties.get(DISPLAY_BRIGHTNESS);
            if (brightnessProperty != null) {
                mMaxDisplayBrightness = brightnessProperty.areaConfigs.size() > 0
                        ? brightnessProperty.areaConfigs.get(0).maxInt32Value : 0;
                if (mMaxDisplayBrightness <= 0) {
                    Slog.w(CarLog.TAG_POWER, "Max display brightness from vehicle HAL is invalid:"
                            + mMaxDisplayBrightness);
                    mMaxDisplayBrightness = 1;
                }
            }
        }
    }

}

VehicleHal.subscribeProperty()

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

/**
 * Subscribes given properties with sampling rate defaults to 0 and no special flags provided.
 *
 * @see #subscribeProperty(HalServiceBase, int, float, int)
 */
public void subscribeProperty(HalServiceBase service, int property)
        throws IllegalArgumentException {
    subscribeProperty(service, property, /* samplingRateHz= */ 0f,
            SubscribeFlags.EVENTS_FROM_CAR);
}


public void subscribeProperty(HalServiceBase service, int property,
        float samplingRateHz, int flags) throws IllegalArgumentException {
    if (DBG) {
        Slog.i(CarLog.TAG_HAL, "subscribeProperty, service:" + service
                + ", " + toCarPropertyLog(property));
    }
    VehiclePropConfig config;
    synchronized (mLock) {
        config = mAllProperties.get(property);
    }

    if (config == null) {
        throw new IllegalArgumentException("subscribe error: config is null for property 0x"
                + toHexString(property));
    } else if (isPropertySubscribable(config)) {
        SubscribeOptions opts = new SubscribeOptions();
        opts.propId = property;
        opts.sampleRate = samplingRateHz;
        opts.flags = flags;
        synchronized (mLock) {
            assertServiceOwnerLocked(service, property);
            mSubscribedProperties.put(property, opts);
        }
        try {
            mHalClient.subscribe(opts);
        } catch (RemoteException e) {
            Slog.e(CarLog.TAG_HAL, "Failed to subscribe to " + toCarPropertyLog(property),
                    e);
        }
    } else {
        Slog.e(CarLog.TAG_HAL, "Cannot subscribe to " + toCarPropertyLog(property));
    }
}

HalClient.subscribe()

packages/services/Car/service/src/com/android/car/hal/HalClient.java

public void subscribe(SubscribeOptions... options) throws RemoteException {
    mVehicle.subscribe(mInternalCallback, new ArrayList<>(Arrays.asList(options)));
}

最终会调用到 IVehicle.hal 的 subscribe(),也就是 VehicleHalManager.cpp 的 subscribe()

VehicleHalManager.subscribe()

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp

Return<StatusCode> VehicleHalManager::subscribe(const sp<IVehicleCallback> &callback,
                                                const hidl_vec<SubscribeOptions> &options) {
    hidl_vec<SubscribeOptions> verifiedOptions(options);  // 创建一个与options相同的verifiedOptions向量

    for (size_t i = 0; i < verifiedOptions.size(); i++) {  // 遍历verifiedOptions向量
        SubscribeOptions& ops = verifiedOptions[i];  // 获取当前遍历到的元素
        auto prop = ops.propId;  // 获取ops的propId属性

        const auto* config = getPropConfigOrNull(prop);  // 根据propId获取属性配置信息
        if (config == nullptr) {
            ALOGE("Failed to subscribe: config not found, property: 0x%x", prop);
            return StatusCode::INVALID_ARG;  // 返回无效参数错误码
        }

        if (ops.flags == SubscribeFlags::UNDEFINED) {  // 如果ops的flags属性为未定义
            ALOGE("Failed to subscribe: undefined flag in options provided");  // 打印错误信息
            return StatusCode::INVALID_ARG;  // 返回无效参数错误码
        }

        if (!isSubscribable(*config, ops.flags)) {  // 如果属性不可订阅
            ALOGE("Failed to subscribe: property 0x%x is not subscribable", prop);  // 打印错误信息
            return StatusCode::INVALID_ARG;  // 返回无效参数错误码
        }

        ops.sampleRate = checkSampleRate(*config, ops.sampleRate);  // 检查并更新ops的sampleRate属性
    }

    std::list<SubscribeOptions> updatedOptions;  // 创建一个空的updatedOptions列表
    auto res = mSubscriptionManager.addOrUpdateSubscription(getClientId(callback),
                                                            callback, verifiedOptions,
                                                            &updatedOptions);  // 添加或更新订阅信息,并将更新后的选项存储在updatedOptions列表中
    if (StatusCode::OK != res) {
        ALOGW("%s failed to subscribe, error code: %d", __func__, res);
        return res;  // 返回错误码
    }

    for (auto opt : updatedOptions) {  // 遍历updatedOptions列表
        mHal->subscribe(opt.propId, opt.sampleRate);  // 调用mHal的subscribe方法订阅属性
    }

    return StatusCode::OK;  // 返回成功状态码
}

先检查这属性的配置是否存在,如果不存在则返回错误。接着 SubscriptionManager.addOrUpdateSubscription() 添加或更新订阅信息。

根据前面的分析,mHal 就是 EmulatedVehicleHal , 所以 mHal->subscribe(opt.propId, opt.sampleRate) 就是 EmulatedVehicleHal.subscribe()

EmulatedVehicleHal.subscribe()

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp

StatusCode EmulatedVehicleHal::subscribe(int32_t property, float sampleRate) {
    ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);

    if (isContinuousProperty(property)) {
        mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
    }
    return StatusCode::OK;
}

isContinuousProperty() 改变 VehiclePropConfig 的 changemode 为 CONTINUOUS(即不断的周期性的发送变化)

以上我们只是拿 PowerHalService ,在 VehicleHal.init() 中会遍历所以的 HalService 去做同样的事情,所以 所有属性都subscribe,CarService就可以所有接收到Vehicle HAL发上来的所有属性变化

同理,unsubscribe注销订阅。

set 设置属性

我们还是以 PowerHalService 为例,如下:

packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

private void setPowerState(int state, int additionalParam) {
    if (isPowerStateSupported()) {
        int[] values = { state, additionalParam };
        try {
            mHal.set(VehicleProperty.AP_POWER_STATE_REPORT, 0).to(values);
            Slog.i(CarLog.TAG_POWER, "setPowerState=" + powerStateReportName(state)
                    + " param=" + additionalParam
                    + " VehicleProperty.AP_POWER_STATE_REPORT=" + VehicleProperty.AP_POWER_STATE_REPORT);
        } catch (ServiceSpecificException e) {
            Slog.e(CarLog.TAG_POWER, "cannot set to AP_POWER_STATE_REPORT", e);
        }
    }
}

mHal 是 VehicleHal,所以会调到 VehicleHal.set() 。看到调到的 VehicleHal.set() 之后,我突然觉得用这个例子来举例不太好。 这里我就用一个简单的代码流程来举例非 car-service 进程怎么设置属性的。

  • CarHvacManager.setBooleanProperty()
packages/services/Car/car-lib/src/android/car/hardware/hvac/CarHvacManager.java

public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val) {
    if (mHvacPropertyIds.contains(propertyId)) {
        mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
    }
}
  • CarPropertyManager.setProperty()
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java

public void setBooleanProperty(int prop, int areaId, boolean val) {
    setProperty(Boolean.class, prop, areaId, val);
}

public <E> void setProperty(@NonNull Class<E> clazz, int propId, int areaId, @NonNull E val) {
    ...

    try {
        mService.setProperty(new CarPropertyValue<>(propId, areaId, val),
                mCarPropertyEventToService);
    ...
}
  • CarPropertyService.setProperty()
packages/services/Car/service/src/com/android/car/CarPropertyService.java

@Override
public void setProperty(CarPropertyValue prop, ICarPropertyEventListener listener) {
    ...
    mHal.setProperty(prop);
    ...
}

这里的 mHal 是 PropertyHalService

  • PropertyHalService.set()
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java

public void setProperty(CarPropertyValue prop) {
    ...
    mVehicleHal.set(halProp);
}
  • VehicleHal.setValue()
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

protected void set(VehiclePropValue propValue) {
    mHalClient.setValue(propValue);
}
  • HalClient.set()
packages/services/Car/service/src/com/android/car/hal/HalClient.java

public void setValue(VehiclePropValue propValue) {
    return mVehicle.set(propValue);
}

好,走到这里已经很清晰了。我们还是回到刚才的例子当中。

VehicleHal.set()

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

@CheckResult
VehiclePropValueSetter set(int propId, int areaId) {
    return new VehiclePropValueSetter(mHalClient, propId, areaId);
}

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

final class VehiclePropValueSetter {
    final WeakReference<HalClient> mClient;
    final VehiclePropValue mPropValue;

    private VehiclePropValueSetter(HalClient client, int propId, int areaId) {
        mClient = new WeakReference<>(client);
        mPropValue = new VehiclePropValue();
        mPropValue.prop = propId;
        mPropValue.areaId = areaId;
    }

    void to(boolean value) {
        to(value ? 1 : 0);
    }

    void to(int value) {
        mPropValue.value.int32Values.add(value);
        submit();
    }

    void to(int[] values) {
        for (int value : values) {
            mPropValue.value.int32Values.add(value);
        }
        submit();
    }

    void to(Collection<Integer> values) {
        mPropValue.value.int32Values.addAll(values);
        submit();
    }

    void submit() {
        HalClient client =  mClient.get();
        if (client != null) {
            if (DBG) {
                Slog.i(CarLog.TAG_HAL, "set, " + toCarPropertyLog(mPropValue.prop)
                        + toCarAreaLog(mPropValue.areaId));
            }
            client.setValue(mPropValue);
        }
    }
}

VehicleHal 里有几个 set() 函数,不管是那个 set() 函数,最终都是调 mHalClient.setValue(propValue) 设置属性。

HalClient.setValue()

还记得之前在 VehicleHal 构造函数里的 vehicle 是从哪里来的吗? 其实 CarService.getVehicle() 获取到并通过构造 ICarImpl 一步一步传进来的。

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public VehicleHal(Context context, IVehicle vehicle) {
    ...
    mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(),
            /* callback= */ this);
}

所以 mVehicle 就是 VehicleHal 。也就是 IVehicle.hal 的 set() 接口。 最终是调到 VehicleHalManager.cpp 的 set() 接口。

packages/services/Car/service/src/com/android/car/hal/HalClient.java

public void setValue(VehiclePropValue propValue) {
    ...
    return mVehicle.set(propValue);
    ...
}

VehicleHalManager.set()

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp

/**
 * @brief 设置车辆属性值
 * @param value 要设置的属性值
 * @return 返回设置结果的状态码
 */
Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {
    auto prop = value.prop; // 获取属性
    const auto* config = getPropConfigOrNull(prop); // 获取属性配置

    if (config == nullptr) { // 如果配置为空
        ALOGE("Failed to set value: config not found, property: 0x%x", prop);
        return StatusCode::INVALID_ARG;
    }

    if (!checkWritePermission(*config)) { // 如果没有写权限
        return StatusCode::ACCESS_DENIED;
    }

    handlePropertySetEvent(value); // 处理属性设置事件

    auto status = mHal->set(value); // 调用mHal的set方法设置属性值

    return Return<StatusCode>(status); // 返回设置结果的状态码
}

其中这里的 handlePropertySetEvent() 函数非常重要,主要是用来调用 SubscriptionManager 把事件回调到客户端的;关于这一点,我们后面会分析。

现在先看 mHal->set(value) ,还是根据前面的分析,mHal 就是 EmulatedVehicleHal。

EmulatedVehicleHal.set()

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp

StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
     ...

    // 将值发送给车辆服务器,服务器将与(真实或模拟的)汽车通信
    auto setValueStatus = mVehicleClient->setProperty(propValue, updateStatus);
    if (setValueStatus != StatusCode::OK) {
        return setValueStatus;
    }

    return StatusCode::OK;
}

通过 VehicleHal 初始化的流程其实可以知道,mVehicleClient 就是 VehicleHalClient 。但这里显然是预留的厂商实现的。 我们通过厂商的代码可以知道 mVehicleClient 是 VehicleClientImpl 。

StatusCode VehicleClientImpl::setProperty(const VehiclePropValue& value, bool updateStatus) {  
    return mVehicleServer->onSetProperty(value);  
}
StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value) {
    ...
}

这里就涉及到厂商自己的业务逻辑了,而从这里我们也知道了,aosp 里 VehicleService 初始化时,并没有创建 VehicleHalClient、VehicleHalServer;而是需要厂商自己的创建。

1. class VehicleHalServer : public property::IPropertyTransfer

2.  VehicleHalServer::initAllProperties() 会调用 prop->init(this)

3. void Property::init(IPropertyTransfer* transfer) {
    mProperty->registerWritePropValueListener(  
                [transfer](const VehiclePropValue& value, CommitMode mode, bool updateStatus) {  
                transfer->onPropertyValue(value, mode, updateStatus);  
              });
}

4. mReportQueue.push(propValue);

5.  PropValueStore::PropValueStore() : mReportQueue(true) {
        mBatchTaskConsumer.run(&mReportQueue, std::bind(&PropValueStore::onVehiclePropertyValueFromStore,this,std::placeholders::_1), "ReportConsumer");
    }

VehicleHalServer::onSetProperty() ->
    IProperty::onSetPropertyValue() ->
        Area::onSetPropertyAreaValue ->
            IProperty::writeToStore() ->
                (由1,2,3可知)
                VehicleHalServer::onPropertyValue() ->
                    PropValueStore::writeValue() ->
                        (由4,5可知)
                        PropValueStore::onVehiclePropertyValueFromStore() ->
                            VehicleHalClient::onPropertyValue()
                            DHUVehicleHal::onPropertyValue()

最终会调到 VehiclePropertyStore 去写属性

VehiclePropertyStore.writeValue()

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp

bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
                                        bool updateStatus) {
    MuxGuard g(mLock);

    // 属性id是否已经注册,如果当前属性id没有注册,则返回false,写入失败。
    if (!mConfigs.count(propValue.prop)) return false;


    RecordId recId = getRecordIdLocked(propValue); // 获取记录ID
    VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId)); // 获取要更新的值

    // 如果当前没有保存该属性,则加入一条新的记录
    if (valueToUpdate == nullptr) {
        mPropertyValues.insert({ recId, propValue });
        return true;
    }

    // 如果要更新的值的时间戳大于propValue的时间戳,则返回false
    if (valueToUpdate->timestamp > propValue.timestamp) {
        return false;
    }

    // 更新valueToUpdate的时间戳和值
    // propertyStore中的时间戳应该只由服务器端更新,它表示服务器生成事件的时间
    valueToUpdate->timestamp = propValue.timestamp;
    valueToUpdate->value = propValue.value;

    // 如果需要更新状态,则更新valueToUpdate的状态
    if (updateStatus) {
        valueToUpdate->status = propValue.status;
    }

    return true;
}
  • 如果要写的属性id 还没有注册,则不写入值,返回失败
  • 如果要写的属性id 还没有保存过,这保存在 mPropertyValues 中
  • 如果要更新的值的时间戳小于 propValue 的时间戳,则更新

这里有个疑问,更新的值并没有更新到 mPropertyValues,那下次通过 get() 获取不就有问题么?

VehicleHalManager.handlePropertySetEvent()

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp

void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
    auto clients =
        mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::EVENTS_FROM_ANDROID);
    for (const auto& client : clients) {
        client->getCallback()->onPropertySet(value);
    }
}

hardware/interfaces/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp

std::list<sp<HalClient>> SubscriptionManager::getSubscribedClients(int32_t propId,
                                                                   SubscribeFlags flags) const {
    MuxGuard g(mLock);
    return getSubscribedClientsLocked(propId, flags);
}

std::list<sp<HalClient>> SubscriptionManager::getSubscribedClientsLocked(
    int32_t propId, SubscribeFlags flags) const {
    std::list<sp<HalClient>> subscribedClients;

    sp<HalClientVector> propClients = getClientsForPropertyLocked(propId);
    if (propClients.get() != nullptr) {
        for (size_t i = 0; i < propClients->size(); i++) {
            const auto& client = propClients->itemAt(i);
            if (client->isSubscribed(propId, flags)) {
                subscribedClients.push_back(client);
            }
        }
    }

    return subscribedClients;
}

handlePropertySetEvent 调用 SubscriptionManager.getSubscribedClients() 返回订阅的HalClient对象list列表;然后会遍历 HalClient 调用其 onPropertySet(value) 回调接口。

VehicleCallback

packages/services/Car/service/src/com/android/car/hal/HalClient.java

final class HalClient {

    private final IVehicleCallback mInternalCallback;

    HalClient(IVehicle vehicle, Looper looper, IVehicleCallback callback,
            int waitCapMs, int sleepMs) {
        mInternalCallback = new VehicleCallback(handler);
    }

    private static final class VehicleCallback extends IVehicleCallback.Stub {
        private final Handler mHandler;

        VehicleCallback(Handler handler) {
            mHandler = handler;
        }

        @Override
        public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {
            mHandler.sendMessage(Message.obtain(
                    mHandler, CallbackHandler.MSG_ON_PROPERTY_EVENT, propValues));
        }

        @Override
        public void onPropertySet(VehiclePropValue propValue) {
            mHandler.sendMessage(Message.obtain(
                    mHandler, CallbackHandler.MSG_ON_PROPERTY_SET, propValue));
        }

        @Override
        public void onPropertySetError(int errorCode, int propId, int areaId) {
            mHandler.sendMessage(Message.obtain(
                    mHandler, CallbackHandler.MSG_ON_SET_ERROR,
                    new PropertySetError(errorCode, propId, areaId)));
        }
    }
}

回调 onPropertySet() 被触发后,通过sendMessage(),然后 handlemessage() 处理消息。 最后调回到 VehicleHal.onPropertySet() 。

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

@Override  
public void onPropertySet(VehiclePropValue value) {  
    // No need to handle on-property-set events in HAL service yet.  
}

get 获取属性

我们还是以 PowerHalService 为例,如下:

packages/services/Car/service/src/com/android/car/hal/PowerHalService.java

@Nullable
public PowerState getCurrentPowerState() {
    int[] state;
    try {
        state = mHal.get(int[].class, VehicleProperty.AP_POWER_STATE_REQ);
    } catch (ServiceSpecificException e) {
        Slog.e(CarLog.TAG_POWER, "Cannot get AP_POWER_STATE_REQ", e);
        return null;
    }
    return new PowerState(state[VehicleApPowerStateReqIndex.STATE],
            state[VehicleApPowerStateReqIndex.ADDITIONAL]);
}

mHal 是 VehicleHal,所以会调到 VehicleHal.get() 。

这里我们还是用一个简单的代码流程来举例非 car-service 进程怎么获取属性的。

  • CarHvacManager.getIntProperty()
packages/services/Car/car-lib/src/android/car/hardware/hvac/CarHvacManager.java

public int getIntProperty(@PropertyId int propertyId, int area) {
    return mCarPropertyMgr.getIntProperty(propertyId, area);
}
  • CarPropertyManager.getProperty()
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java

public int getIntProperty(int prop, int area) {
    checkSupportedProperty(prop);
    CarPropertyValue<Integer> carProp = getProperty(Integer.class, prop, area);
    return handleNullAndPropertyStatus(carProp, area, 0);
}

@Nullable
public <E> CarPropertyValue<E> getProperty(@NonNull Class<E> clazz, int propId, int areaId) {
    ...

    try {
        CarPropertyValue<E> propVal = mService.getProperty(propId, areaId);
        ...
        return propVal;
    ...
}
  • CarPropertyService.getProperty()
packages/services/Car/service/src/com/android/car/CarPropertyService.java

@Override
public CarPropertyValue getProperty(int prop, int zone) {
    ...
    return mHal.getProperty(prop, zone);
}

这里的 mHal 是 PropertyHalService

  • PropertyHalService.get()
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java

@Nullable
public CarPropertyValue getProperty(int mgrPropId, int areaId) throws ServiceSpecificException {
    ...
    VehiclePropValue value = mVehicleHal.get(halPropId, areaId);
    ...
}
  • VehicleHal.get()
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

 public VehiclePropValue get(int propertyId, int areaId) {
    ...
    return mHalClient.getValue(createPropValue(propertyId, areaId));
}
  • HalClient.getValue()
packages/services/Car/service/src/com/android/car/hal/HalClient.java

VehiclePropValue getValue(VehiclePropValue requestedPropValue) {
    ...
    ValueResult res = internalGet(requestedPropValue);
    ...
}


private ValueResult internalGet(VehiclePropValue requestedPropValue) {
    ...
    try {
        mVehicle.get(requestedPropValue,
                (status, propValue) -> {
                    result.status = status;
                    result.propValue = propValue;
                });
    } 
    ...
}

好,走到这里已经很清晰了。我们还是回到刚才的例子当中。

VehicleHal.get()

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

public <T> T get(Class clazz, VehiclePropValue requestedPropValue) {
    VehiclePropValue propValue;
    propValue = mHalClient.getValue(requestedPropValue);

    if (clazz == Long.class || clazz == long.class) {
        return (T) propValue.value.int64Values.get(0);
    } else if (clazz == Integer.class || clazz == int.class) {
        return (T) propValue.value.int32Values.get(0);
    } else if (clazz == Boolean.class || clazz == boolean.class) {
        return (T) Boolean.valueOf(propValue.value.int32Values.get(0) == 1);
    } else if (clazz == Float.class || clazz == float.class) {
        return (T) propValue.value.floatValues.get(0);
    } else if (clazz == Long[].class) {
        Long[] longArray = new Long[propValue.value.int64Values.size()];
        return (T) propValue.value.int32Values.toArray(longArray);
    } else if (clazz == Integer[].class) {
        Integer[] intArray = new Integer[propValue.value.int32Values.size()];
        return (T) propValue.value.int32Values.toArray(intArray);
    } else if (clazz == Float[].class) {
        Float[] floatArray = new Float[propValue.value.floatValues.size()];
        return (T) propValue.value.floatValues.toArray(floatArray);
    } else if (clazz == long[].class) {
        return (T) toLongArray(propValue.value.int64Values);
    } else if (clazz == int[].class) {
        return (T) toIntArray(propValue.value.int32Values);
    } else if (clazz == float[].class) {
        return (T) toFloatArray(propValue.value.floatValues);
    } else if (clazz == byte[].class) {
        return (T) toByteArray(propValue.value.bytes);
    } else if (clazz == String.class) {
        return (T) propValue.value.stringValue;
    } else {
        throw new IllegalArgumentException("Unexpected type: " + clazz);
    }
}

VehicleHal 里有几个 get() 函数,不管是那个 get() 函数,最终都是调 mHalClient.getValue() 获取属性。

HalClient.getValue()

packages/services/Car/service/src/com/android/car/hal/HalClient.java

VehiclePropValue getValue(VehiclePropValue requestedPropValue) {
    final ObjectWrapper<VehiclePropValue> valueWrapper = new ObjectWrapper<>();
    int status = invokeRetriable(() -> {
        ValueResult res = internalGet(requestedPropValue);
        valueWrapper.object = res.propValue;
        return res.status;
    }, mWaitCapMs, mSleepMs);

    ...
}

private ValueResult internalGet(VehiclePropValue requestedPropValue) {
    final ValueResult result = new ValueResult();
    try {
        mVehicle.get(requestedPropValue,
                (status, propValue) -> {
                    result.status = status;
                    result.propValue = propValue;
                });
    } catch (RemoteException e) {
        Slogf.e(TAG, getValueErrorMessage("get", requestedPropValue), e);
        result.status = StatusCode.TRY_AGAIN;
    }

    return result;
}

根据前面的分析 mVehicle 是 VehicleHal 。也就是 IVehicle.hal 的 get() 接口。 最终是调到 VehicleHalManager.cpp 的 get() 接口。

VehicleHalManager.get()

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp

Return<void> VehicleHalManager::get(const VehiclePropValue& requestedPropValue, get_cb _hidl_cb) {
    const auto* config = getPropConfigOrNull(requestedPropValue.prop);  // 获取指定属性的配置信息
    if (config == nullptr) {
        ALOGE("Failed to get value: config not found, property: 0x%x", requestedPropValue.prop);
        _hidl_cb(StatusCode::INVALID_ARG, kEmptyValue);
        return Void();
    }

    if (!checkReadPermission(*config)) {  // 如果没有读取权限
        _hidl_cb(StatusCode::ACCESS_DENIED, kEmptyValue);  // 回调ACCESS_DENIED错误码和空值
        return Void();  // 返回空值
    }

    StatusCode status;
    auto value = mHal->get(requestedPropValue, &status);  // 调用mHal的get方法获取属性值
    _hidl_cb(status, value.get() ? *value : kEmptyValue);  // 回调获取的状态码和属性值(如果有)

    return Void();  // 返回空值
}

还是根据前面的分析,mHal 就是 EmulatedVehicleHal。

EmulatedVehicleHal.get()

hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp

VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
    auto propId = requestedPropValue.prop;
    ALOGV("get(%d)", propId);

    auto& pool = *getValuePool();
    VehiclePropValuePtr v = nullptr; // 定义一个指向VehiclePropValue的智能指针v,并初始化为nullptr

    // 根据propId来获取值
    // OBD2_FREEZE_FRAME 是 0BD 检测到故障信息
    // OBD2_FREEZE_FRAME_INFO 是故障检测到得时间戳
    // 一般要获取 OBD2_FREEZE_FRAME 的数据之前,都要通过 OBD2_FREEZE_FRAME_INFO 获取时间戳。
    //除了这两个属性值,其他的都直接从临时的Store里面获取当前属性的状态值。
    switch (propId) {
        case OBD2_FREEZE_FRAME:
            v = pool.obtainComplex();
            *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
            break;
        case OBD2_FREEZE_FRAME_INFO:
            v = pool.obtainComplex();
            *outStatus = fillObd2DtcInfo(v.get());
            break;
        default:
            // 如果 EmulatedUserHal 支持这个属性,则调用 EmulatedUserHal.onGetProperty() 函数获取属性值
            if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) {
                ALOGI("get(): getting value for prop %d from User HAL", propId);
                const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue);
                if (!ret.ok()) {
                    ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
                    *outStatus = StatusCode(ret.error().code()); 
                } else {
                    auto value = ret.value().get();
                    if (value != nullptr) {
                        ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
                        v = getValuePool()->obtain(*value);
                        *outStatus = StatusCode::OK;
                    } else {
                        ALOGE("get(): User HAL returned null value");
                        *outStatus = StatusCode::INTERNAL_ERROR;
                    }
                }
                break;
            }

            // 空调电源属性 
            if (mHvacPowerProps.count(propId)) {
                auto hvacPowerOn = mPropStore->readValueOrNull(
                    toInt(VehicleProperty::HVAC_POWER_ON),
                    (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
                    VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
                    VehicleAreaSeat::ROW_2_RIGHT));
                if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
                        && hvacPowerOn->value.int32Values[0] == 0) {
                    *outStatus = StatusCode::NOT_AVAILABLE; // 将状态码设置为NOT_AVAILABLE
                    break;
                }
            }

            // mPropStore 就是 VehiclePropertyStore ,也就是从 VehiclePropertyStore 获取属性
            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
            if (internalPropValue != nullptr) {
                v = getValuePool()->obtain(*internalPropValue);
            }

            if (!v) {
                *outStatus = StatusCode::INVALID_ARG;
            } else if (v->status == VehiclePropertyStatus::AVAILABLE) {
                *outStatus = StatusCode::OK;
            } else {
                *outStatus = StatusCode::TRY_AGAIN;
            }
            break;
    }
    if (v.get()) {
        v->timestamp = elapsedRealtimeNano();
    }
    return v;
}

这里其实很简单: - 故障 相关的属性,则相关函数单独出来,但最终都还是调用到 VehiclePropertyStore 里获取的。 - EmulatedUserHal 支持这个属性,则从 EmulatedUserHal 获取 - 空调电源属性,单独处理 - 如果以上情况都不满足,则正常从 VehiclePropertyStore 获取属性。

VehiclePropertyStore

hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp

std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
        const VehiclePropValue& request) const {
    MuxGuard g(mLock);
    RecordId recId = getRecordIdLocked(request);
    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}

std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
        int32_t prop, int32_t area, int64_t token) const {
    RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
    MuxGuard g(mLock);
    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}

const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
        const VehiclePropertyStore::RecordId& recId) const  {
    auto it = mPropertyValues.find(recId);
    return it == mPropertyValues.end() ? nullptr : &it->second;
}

从这里可以看出来,VehicleHal 配置的这些车辆相关的属性,其实并没有通过数据库或者文件进程存储。而是通过 VehiclePropertyStore 存储在内存中。

其实前面我们提到 VehiclePropertyStore 的类,其中有一个 registerProperty() 函数,就是每次进程起来的时候把所有的属性都加载到内存中。

//hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
class EmulatedVehicleHalIface : public VehicleHal{.....}

//hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
class EmulatedVehicleHal : public EmulatedVehicleHalIface{....}

//hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
    auto propId = requestedPropValue.prop;
    auto& pool = *getValuePool();
    VehiclePropValuePtr v = nullptr;

    switch (propId) {
        case OBD2_FREEZE_FRAME:
            v = pool.obtainComplex();
            *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
            break;
        case OBD2_FREEZE_FRAME_INFO:
            v = pool.obtainComplex();
            *outStatus = fillObd2DtcInfo(v.get());
            break;
        default:
            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
            if (internalPropValue != nullptr) {
                v = getValuePool()->obtain(*internalPropValue);
            }
            *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
            break;
    }
    return v;
}
  • VehiclePropertyStore.cpp - readValueOrNull

  • getRecordIdLocked 根据入参VehiclePropValue获取RecordId,关于VehiclePropValue对象可查看上层VehicleHal.java的get函数的流程

  • 调用getValueOrNullLocked,根据RecordId从VehiclePropertyStore中读取

//VehiclePropertyStore.cpp
VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
        const VehiclePropValue& valuePrototype) const {
    RecordId recId = {
        .prop = valuePrototype.prop,
        .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
        .token = 0
    };

    auto it = mConfigs.find(recId.prop);
    if (it == mConfigs.end()) return {};

    if (it->second.tokenFunction != nullptr) {
        recId.token = it->second.tokenFunction(valuePrototype);
    }
    return recId;
}

const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
        const VehiclePropertyStore::RecordId& recId) const  {
    auto it = mPropertyValues.find(recId);
    return it == mPropertyValues.end() ? nullptr : &it->second;
}


//VehiclePropertyStore.h
class VehiclePropertyStore {
    ...
    struct RecordId {
        int32_t prop;
        int32_t area;
        int64_t token;

        bool operator==(const RecordId& other) const;
        bool operator<(const RecordId& other) const;
    };

    using PropertyMap = std::map<RecordId, VehiclePropValue>;
    .....
    PropertyMap mPropertyValues;
}

附录

文中提到的一个接口文件会在编译的时候自动生成,主要目录是在:

out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0

android.hardware.automotive.vehicle@2.0_genc++
android.hardware.automotive.vehicle@2.0_genc++_headers
android.hardware.automotive.vehicle-V2.0-java_gen_java

评论