Android Vehicle HAL架构

2022-09-28 08:23:08 浏览数 (1)

My Table
  • 1. VehicleHAL启动流程
    • 1.1. vehicleHal类图
      • 1.1.1. types.hal/IVehicle.hal/IVehicleCallback.hal
  • 2. VehicleHal初始化流程
    • 2.1. vehiclehal启动序列图
  • 3. 车辆属性类型types.hal
    • 3.1. 车辆属性VehiclePropertyType
    • 3.2. 车辆区域类型VehicleArea
      • 3.2.1. 车辆属性分组类型VehiclePropertyGroup
      • 3.2.2. 车辆窗户区域属性VehicleAreaWindow
    • 3.3. 车辆属性访问权限VehiclePropertyAccess
    • 3.4. 车辆属性变化模式VehiclePropertyChangeMode
    • 3.5. 车辆属性事件订阅信息SubscribeOptions
    • 3.6. 车辆座椅属性VehicleAreaSeat
    • 3.7. 接口调用状态值StatusCode
  • 4. 回调接口函数IVehicleCallback
  • 5. VehicleHal获取/设置属性流程
    • 5.1. subscribe订阅属性
    • 5.2. subscribe序列图
    • 5.3. set设置属性请求流程
    • 5.4. get获取属性请求流程
    • 5.5. set和get属性流程序列图
  • 6. DBus IPC通信方式
    • 6.1. 应用场景
    • 6.2. 通信实现原理
  • 7. 参考

文档内容:1.vehicle HAL架构介绍、详细的启动流程;2.部分车辆属性类型名称说明;3.上层carservice和hal层数据subscribe/set/get流程梳理;4.dbus和vehicle hal连接交互的流程;4.从dbus回调数据返回至APP层的详细流程梳理(最终梳理方法流转调用的流程,绘制序列图)


1. VehicleHAL启动流程

  • 源码位置:hardware/interfaces/automotive/vehicle/2.0/
  1. .rc文件android.hardware.automotive.vehicle@2.0-service.rc启动进程

该文件位于设备系统vendor/etc/init目录

代码语言:javascript复制
//hardware/interfaces/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
    class hal
    user vehicle_network
    group system inet
  1. init进程加载启动/vendor/etc/init目录下的脚本
代码语言:javascript复制
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

1.1. vehicleHal类图

1.1.1. types.hal/IVehicle.hal/IVehicleCallback.hal

均在/hardware/interfaces/automotive/vehicle/2.0/目录下

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

2. VehicleHal初始化流程

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

  • 创建VehiclePropertyStore对象
  • 创建EmulatedVehicleHal对象
  • 创建VehicleEmulator对象
  • 创建VehicleHalManager对象
代码语言:javascript复制
int main(int /* argc */, char* /* argv */ []) {
    //调用VehiclePropertyStore构造函数,构造一个对象
    auto store = std::make_unique<VehiclePropertyStore>();
    //调用EmulatedVehicleHal构造函数,入参VehiclePropertyStore
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
    //调用VehicleEmulator构造函数,入参EmulatedVehicleHal
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    //创建VehicleHalManager对象
    auto service = std::make_unique<VehicleHalManager>(hal.get());

    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");
    joinRpcThreadpool();//将当前通信加入线程池进行循环

    return 1;
}

——> VehicleHalManager构造函数中调用init初始化:

  • 重置HidlVecOfVehiclePropValuePool HIDL属性对象池大小
  • 开启事件消费着队列
  • VehicleHal初始化
代码语言:javascript复制
VehicleHalManager(VehicleHal* vehicleHal)
    : mHal(vehicleHal),
      mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
                                     this, std::placeholders::_1)) {
    init();
}

void VehicleHalManager::init() {
    ALOGI("VehicleHalManager::init");
    //1.重置HidlVecOfVehiclePropValuePool HIDL属性对象池大小为20
    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
    //2.开启事件消费着队列
    mBatchingConsumer.run(&mEventQueue,
                          kHalEventBatchingTimeWindow,
                          std::bind(&VehicleHalManager::onBatchHalEvent,
                                    this, _1));
    //3.VehicleHal初始化
    mHal->init(&mValueObjectPool,
               std::bind(&VehicleHalManager::onHalEvent, this, _1),
               std::bind(&VehicleHalManager::onHalPropertySetError, this,
                         _1, _2, _3));

    // Initialize index with vehicle configurations received from VehicleHal.
    //4.初始化从VehicleHal收到的vehicle属性的索引
    auto supportedPropConfigs = mHal->listProperties();
    mConfigIndex.reset(new VehiclePropConfigIndex(supportedPropConfigs));

    std::vector<int32_t> supportedProperties(
        supportedPropConfigs.size());
    for (const auto& config : supportedPropConfigs) {
        supportedProperties.push_back(config.prop);
    }
}

——> VehicleHal.h初始化做了以下操作: 1.初始化mValuePool 2.初始化mOnHalEvent 3.初始化mOnHalPropertySetError变量 4.调用onCreate

代码语言:javascript复制
    void init(
        VehiclePropValuePool* valueObjectPool,
        const HalEventFunction& onHalEvent,
        const HalErrorFunction& onHalError) {
        mValuePool = valueObjectPool;
        mOnHalEvent = onHalEvent;
        mOnHalPropertySetError = onHalError;

        onCreate();
    }

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

2.1. vehiclehal启动序列图


3. 车辆属性类型types.hal

3.1. 车辆属性VehiclePropertyType

  • 定义在hardware/interfaces/automotive/vehicle/2.0/types.hal(以下属性定义均在该文件内)

在上面的onCreate函数最后会调用initObd2LiveFrame和initObd2FreezeFrame —–> 调用VehicleUtils.cpp createVehiclePropValue(VehiclePropertyType::MIXED, 0)即车辆属性

代码语言:javascript复制
std::unique_ptr<VehiclePropValue> createVehiclePropValue(
    VehiclePropertyType type, size_t vecSize) {
    auto val = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
    switch (type) {
        case VehiclePropertyType::INT32:      // fall through
        case VehiclePropertyType::INT32_VEC:  // fall through
        case VehiclePropertyType::BOOLEAN:
            val->value.int32Values.resize(vecSize);
            break;
        case VehiclePropertyType::FLOAT:      // fall through
        case VehiclePropertyType::FLOAT_VEC:
            val->value.floatValues.resize(vecSize);
            break;
        case VehiclePropertyType::INT64:
        case VehiclePropertyType::INT64_VEC:
            val->value.int64Values.resize(vecSize);
            break;
        case VehiclePropertyType::BYTES:
            val->value.bytes.resize(vecSize);
            break;
        case VehiclePropertyType::STRING:
        case VehiclePropertyType::MIXED:
            break; // Valid, but nothing to do.
        default:
            ALOGE("createVehiclePropValue: unknown type: %d", type);
            val.reset(nullptr);
    }
    return val;
}

此处这些值在hardware/interfaces/automotive/vehicle/2.0/types.hal中十六进制定义:

代码语言:javascript复制
enum VehiclePropertyType : int32_t {
    STRING          = 0x00100000,
    BOOLEAN         = 0x00200000,
    INT32           = 0x00400000,
    INT32_VEC       = 0x00410000,
    INT64           = 0x00500000,
    INT64_VEC       = 0x00510000,
    FLOAT           = 0x00600000,
    FLOAT_VEC       = 0x00610000,
    BYTES           = 0x00700000,
    //混合类型组合
    MIXED           = 0x00e00000,
    MASK            = 0x00ff0000
};

3.2. 车辆区域类型VehicleArea

定义在hardware/interfaces/automotive/vehicle/2.0/types.hal

代码语言:javascript复制
enum VehicleArea : int32_t {
    GLOBAL      = 0x01000000,   //全局
    /** WINDOW maps to enum VehicleAreaWindow 窗户区域*/
    WINDOW      = 0x03000000,
    /** MIRROR maps to enum VehicleAreaMirror 反光镜区域*/
    MIRROR      = 0x04000000,
    /** SEAT maps to enum VehicleAreaSeat 座位区域*/
    SEAT        = 0x05000000,
    /** DOOR maps to enum VehicleAreaDoor 车门区域*/
    DOOR        = 0x06000000,
    /** WHEEL maps to enum VehicleAreaWheel 车轮区域*/
    WHEEL       = 0x07000000,
    MASK        = 0x0f000000,
};

3.2.1. 车辆属性分组类型VehiclePropertyGroup

  • 定义在hardware/interfaces/automotive/vehicle/2.0/types.hal
代码语言:javascript复制
enum VehiclePropertyGroup : int32_t {
    //hardware/interfaces/automotive/vehicle/2.0/types.hal
    SYSTEM      = 0x10000000,

    //vendor 可定制修改
    VENDOR      = 0x20000000,

    MASK        = 0xf0000000,
};

3.2.2. 车辆窗户区域属性VehicleAreaWindow

代码语言:javascript复制
/**
 * Various windshields/windows in the car.
 */
enum VehicleAreaWindow : int32_t {
    FRONT_WINDSHIELD  = 0x00000001,
    REAR_WINDSHIELD   = 0x00000002,
    ROW_1_LEFT        = 0x00000010,
    ROW_1_RIGHT       = 0x00000040,
    ROW_2_LEFT        = 0x00000100,
    ROW_2_RIGHT       = 0x00000400,
    ROW_3_LEFT        = 0x00001000,
    ROW_3_RIGHT       = 0x00004000,

    ROOF_TOP_1        = 0x00010000,
    ROOF_TOP_2        = 0x00020000,

};

3.3. 车辆属性访问权限VehiclePropertyAccess

  • 定义在hardware/interfaces/automotive/vehicle/2.0/types.hal
代码语言:javascript复制
enum VehiclePropertyAccess : int32_t {
    NONE = 0x00,
    READ = 0x01,
    WRITE = 0x02,
    READ_WRITE = 0x03,
};

3.4. 车辆属性变化模式VehiclePropertyChangeMode

  • 定义在hardware/interfaces/automotive/vehicle/2.0/types.hal
代码语言:javascript复制
enum VehiclePropertyChangeMode : int32_t {
    //静态属性,不支持subscribe订阅,只能get获取
    STATIC = 0x00,
    //ONCHANGE这个类型的属性当变化时必须上报
    //调用get接口获取当前值;
    //set接口是异步的,当属性读取(调用get接口)在属性设置(调用set接口)之后,也有可能获取到的是旧值,除非从硬件反馈属性的确发送变化
    //我们大多数属性都是这个类型
    ON_CHANGE = 0x01,
    //CONTINUOUS类型的属性会不断的周期性的发送变化。比如速度和方向盘角度等,需要设置采样率范围
    CONTINUOUS = 0x02,
};

3.5. 车辆属性事件订阅信息SubscribeOptions

代码语言:javascript复制
struct SubscribeOptions {
    /** Property to subscribe */
    //订阅的属性的Id
    int32_t propId;

    //以Hz为单位的采样率
    //必须为具有VehiclePropertyChangeMode::CONTINUOUS的属性提供
    //值必须包含在VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate给定的范围内
    //该值标志每秒客户端想要接受多少更新
    float sampleRate;

    /** 指定监听哪个事件的标志 */
    SubscribeFlags flags;
};

enum SubscribeFlags : int32_t {
    UNDEFINED = 0x0,
    //订阅来自vehicle hal的属性,极有可能来自于车辆本身
    EVENTS_FROM_CAR = 0x1,
    //当被vehicle hal的client客户端(即car service)调用set时使用该标志订阅事件
    EVENTS_FROM_ANDROID = 0x2,
};

3.6. 车辆座椅属性VehicleAreaSeat

代码语言:javascript复制
/**
 * Various Seats in the car.
 */
enum VehicleAreaSeat : int32_t {
    ROW_1_LEFT   = 0x0001,
    ROW_1_CENTER = 0x0002,
    ROW_1_RIGHT  = 0x0004,
    ROW_2_LEFT   = 0x0010,
    ROW_2_CENTER = 0x0020,
    ROW_2_RIGHT  = 0x0040,
    ROW_3_LEFT   = 0x0100,
    ROW_3_CENTER = 0x0200,
    ROW_3_RIGHT  = 0x0400
};

3.7. 接口调用状态值StatusCode

代码语言:javascript复制
enum StatusCode : int32_t {
    OK = 0,
    /** Try again. */
    TRY_AGAIN = 1,
    /** Invalid argument provided. */
    INVALID_ARG = 2,

    /**
     * This code must be returned when device that associated with the vehicle
     * property is not available. For example, when client tries to set HVAC
     * temperature when the whole HVAC unit is turned OFF.
     */
    NOT_AVAILABLE = 3,

    /** Access denied */
    ACCESS_DENIED = 4,
    /** Something unexpected has happened in Vehicle HAL */
    //vehicle hal内部错误
    INTERNAL_ERROR = 5,
};

4. 回调接口函数IVehicleCallback

  • 定义于:hardware/interfaces/automotive/vehicle/2.0/IVehicleCallback.hal
代码语言:javascript复制
interface IVehicleCallback {
    /**
     * @param values that has been updated.入参时已经更新的value值
     */
    //每当一个API使用者已经订阅的变量需要去report报告的时候,事件回调就会发生
    //这可能基于阙值和频率(一个规律性的订阅,看订阅调用的参数)或者set函数被调用并且实际的变化需要report报告
    //这个回调和属性的零界值或更新频率有关
    oneway onPropertyEvent(vec<VehiclePropValue> propValues);

    /**
     * @param value Value that was set by a client.被上层客户端设置的value的值
     */
    //如果客户端已经订阅了一个SubscribeFlags::EVENTS_FROM_ANDROID标志的属性,并且调用了set方法,该函数会被触发回调
    //这些事件必须没有任何batching批处理,就立刻传递给订阅者
    //当客户端订阅属性时使用SubscribeFlags::SET_CALL标志,并且当IVehicle的set接口被调用时就会回调这个接口
    oneway onPropertySet(VehiclePropValue propValue);

    /**
     * @param errorCode - any value from StatusCode enum.来自状态码枚举中的任何值
     * @param property - a property where error has happened.
     * @param areaId - bitmask that specifies in which areas the problem has
     *                 occurred, must be 0 for global properties
     */
    //set属性通常是异步操作
    //因此即使客户端从set接口函数接收到StatusCode::OK的状态码,这并不能保证value被成功传递到车载网络
    //如果发生这种小概率事件,该函数会被调用
    oneway onPropertySetError(StatusCode errorCode,
                              int32_t propId,
                              int32_t areaId);
};

5. VehicleHal获取/设置属性流程

5.1. subscribe订阅属性

CarService在onCreate中创建ICarImpl时,构造函数中new VehicleHal对象,然后又在CarImpl的init函数中调用VehicleHal对象的init函数

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java - 构造函数new各个HalService(继承于PropertyHalServiceBase->基类HalServiceBase),并且new HalClient客户端对象

—-> init函数执行mHalClient.getAllPropConfigs()从Vehicle HAL(IVehicle.hal)获取所有的属性,调用到VehicleHalManager.cpp的该函数

—-> 遍历HALService执行service.takeSupportedProperties获取CarService支持的属性

—–> 在该遍历代码块最后执行service.init()初始化各个HALService

—–> 例如PowerHalService.java - PowerHalService执行init,调用mHal.subscribeProperty

—–> 调用VehicleHal.java的subscribeProperty,然后调用mHalClient.subscribe(opts)

—–> 调用HalClient.java的subscribe,调用mVehicle.subscribe(...)

——> 调用hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal的subscribe

——> 调用hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp的subscribe

(1) ——-> SubscriptionManager.cpp - addOrUpdateSubscription (2) ——> subscribe,返回statusCode结果状态码

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

代码语言:javascript复制
//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
....

此时所有属性都subscribe,CarService就可以所有接收到Vehicle HAL发上来的所有属性变化

同理,unsubscribe注销订阅

5.2. subscribe序列图


5.3. set设置属性请求流程

例如空调APP的设置开关状态:packages/apps/Car/Hvac/src/com/android/car/hvac/HvacController.java - setHvacPowerState

—–> packages/services/Car/car-lib/src/android/car/hardware/hvac/CarHvacManager.java - setBooleanProperty

—–> packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java(大部分会使用该manager) - setBooleanProperty

——> setProperty(将propId,area,value三个参数组成CarPropertyValue参数并设置到CarPropertyServiceBase端)

——> packages/services/Car/car-lib/src/android/car/hardware/property/ICarProperty.aidl - setProperty[AIDL通信]

—–> packages/services/Car/service/src/com/android/car/CarPropertyService.java - setProperty

代码语言:javascript复制
public class CarPropertyService extends ICarProperty.Stub
        implements CarServiceBase, PropertyHalServiceBase.PropertyHalListener {
            ......
    private final PropertyHalServiceBase mHal;

    @Override
    public void setProperty(CarPropertyValue prop) {
        ICarImpl.assertPermission(mContext, mPermission);
        mHal.setProperty(prop);
    }

—–> ./hal/PropertyHalServiceBase.java - setProperty

代码语言:javascript复制
    public void setProperty(CarPropertyValue prop) {
        //获取到halPropId,这个halPropId是Vehiclehal定义生成的
        int halPropId = managerToHalPropId(prop.getPropertyId());
        //将CarPropertyValue参数转换成VehiclePropValue
        VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
        try {
            mVehicleHal.set(halProp);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x"   toHexString(halPropId), e);
            throw new RuntimeException(e);
        }
    }

——> ./hal/VehicleHal.java - set()

——> ./hal/HalClient.java - setValued调用mVehicle.set(propValue)

——> hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal - set(VehiclePropValue propValue)…

——> hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp - set设置属性

(1) 回调流程: —-> handlePropertySetEvent调用SubscriptionManager.cpp的getSubscribedClients返回订阅的HalClient对象list列表 —-> handlePropertySetEvent最后会遍历HALClient列表,然后回调client->getCallback()->onPropertySet(value); —-> HalClient.java - class VehicleCallback extends IVehicleCallback.Stub从而调用onPropertySet的sendMessage,然后handlemessage处理消息

(2) —-> EmulatedVehicleHal.cpp - set函数(和get相同),此处会返回statusCode设置结果的状态码

—–> SendMsgtoVehicle(msg)


5.4. get获取属性请求流程

packages/services/Car/car-lib/src/android/car/hardware/CarVendorExtensionManager.java - getProperty

—–> CarPropertyManagerBase.java - getProperty

—–> ICarProperty.aidl - getProperty[AIDL通信]

—–> packages/services/Car/service/src/com/android/car/CarPropertyServiceBase.java - getProperty

代码语言:javascript复制
public class CarPropertyServiceBase extends ICarProperty.Stub
        implements CarServiceBase, PropertyHalServiceBase.PropertyHalListener {
            ......
    private final PropertyHalServiceBase mHal;

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

—–> ./hal/PropertyHalServiceBase.java - setProperty

代码语言:javascript复制
    public CarPropertyValue getProperty(int mgrPropId, int areaId) {
        int halPropId = managerToHalPropId(mgrPropId);
   
        VehiclePropValue value = null;
        try {
            value = mVehicleHal.get(halPropId, areaId);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x"   toHexString(halPropId), e);
        }

        return value == null ? null : toCarPropertyValue(value, mgrPropId);
    }

——> ./hal/VehicleHal.java - get()设置VehiclePropValue对象,并初始化参数

代码语言:javascript复制
    public VehiclePropValue get(int propertyId, int areaId) throws PropertyTimeoutException {
        VehiclePropValue propValue = new VehiclePropValue();
        propValue.prop = propertyId;
        propValue.areaId = areaId;
        return mHalClient.getValue(propValue);
    }

——> ./hal/HalClient.java - getValue调用mVehicle.get...

——> hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal - get(VehiclePropValue requestedPropValue)…

——> hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp - get属性

——-> hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp - get函数

代码语言:javascript复制
//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中读取

代码语言:javascript复制
//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;
}

5.5. set和get属性流程序列图


6. DBus IPC通信方式

  • DBus是一种低延迟、低开销、高可用性的IPC(interprocess communication )机制总线系统,用于进程间的通信(会话总线)或进程与内核的通信(系统总线)

6.1. 应用场景

根据DBUS消息类型可知,DBUS提供一种高效的进程间通信机制,主要用于进程间函数调用以及进程间信号广播。

  1. 函数调用:DBUS可以实现进程间函数调用,进程A发送函数调用的请求(Methodcall消息),经过总线转发至进程B。进程B将应答函数返回值(Method return消息)或者错误消息(Error消息)
  2. 消息广播:进程间消息广播(Signal消息)不需要响应,接收方需要向总线注册感兴趣的消息类型,当总线接收到“Signal消息”类型的消息时,会将消息转发至希望接收的进程

6.2. 通信实现原理

在DBUS通信过程中,存在一个后台进程(BUS Daemon Process)。后台进程和普通进程间信息交互是通过域套接字进行通信


7. 参考

  • Item 21: 比起直接使用new优先使用std::make_unique和std::make_shared

0 人点赞