Vhal 接口与 架构

2025-09-01

Vhal提供的接口

提供的方法

方法 参数 返回值
getAllPropConfigs   HIDL: vec<VehiclePropConfig>
AIDL: VehiclePropConfigs
getPropConfigs HIDL: vec<int32_t> props
AIDL: int[] props
HIDL: StatusCode, vec<VehiclePropConfig>
AIDL: VehiclePropConfigs
HIDL: get
AIDL: getValues
HIDL: VehiclePropValue requestedPropValue
AIDL: IVehicleCallback callback, GetValueRequests requests
HIDL: StatusCode status, VehiclePropValue propValue
HIDL: set
AIDL: setValues
HIDL: VehiclePropValue propValue
AIDL: IVehicleCallback callback, SetValueRequests requests
HIDL: StatusCode status
subscribe HIDL: IVehicleCallback callback, vec<SubscribeOptions> options
AIDL: IVehicleCallback callback, SubscribeOptions[] options, int maxSharedMemoryFileCount
HIDL: StatusCode status
unsubscribe HIDL: IVehicleCallback callback, int32_t propId
AIDL: IVehicleCallback callback, int[] propIds
HIDL: StatusCode status

一些参数与返回值的定义

VehicleProperty

VehicleProperty定义为enum类型,其中每个property为32位整数:

31        27        23               15                                 0
+---------+---------+----------------+----------------------------------+
|  group  |   area  |      type      |               id                 |
+---------+---------+----------------+----------------------------------+

VehiclePropConfig

HIDL :

struct VehiclePropConfig {
    int32_t prop;
    VehiclePropertyAccess access;
    VehiclePropertyChangeMode changeMode;
    vec<VehicleAreaConfig> areaConfigs;
    vec<int32_t> configArray;
    string configString;
    float minSampleRate;
    float maxSampleRate;
};

AIDL:

parcelable VehiclePropConfig {

    int prop;

    android.hardware.automotive.vehicle.VehiclePropertyAccess access = android.hardware.automotive.vehicle.VehiclePropertyAccess.NONE;

    android.hardware.automotive.vehicle.VehiclePropertyChangeMode changeMode = android.hardware.automotive.vehicle.VehiclePropertyChangeMode.STATIC;

    android.hardware.automotive.vehicle.VehicleAreaConfig[] areaConfigs;

    int[] configArray;

    @utf8InCpp 
    String configString;

    float minSampleRate;

    float maxSampleRate;
}

parcelable VehiclePropConfigs {
    android.hardware.automotive.vehicle.VehiclePropConfig[] payloads;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

,其中一些字段解释如下:

accessNONE
READ只读
WRITE只写
READ_WRITE可读写
changeModeSTATIC不变化,不支持subscribe
ON_CHANGEget返回当前值,值改变时该类型属性必须触发值改变事件
CONTINUOUSsubscribe 必须采用一定的sample rate

VehicleAreaConfig的定义如下:

HIDL:

struct VehicleAreaConfig {

    int32_t areaId;

    int32_t minInt32Value;
    int32_t maxInt32Value;

    int64_t minInt64Value;
    int64_t maxInt64Value;

    float minFloatValue;
    float maxFloatValue;
};

AIDL:

parcelable VehicleAreaConfig {
    int areaId;

    int minInt32Value;
    int maxInt32Value;

    long minInt64Value;
    long maxInt64Value;

    float minFloatValue;
    float maxFloatValue;

    @nullable 
    long[] supportedEnumValues;
}

VehiclePropValue

HIDL:

struct VehiclePropValue {
    int64_t timestamp;

    int32_t areaId;

    int32_t prop;

    VehiclePropertyStatus status;

    struct RawValue {

        vec<int32_t> int32Values;

        vec<float> floatValues;

        vec<int64_t> int64Values;

        vec<uint8_t> bytes;

        string stringValue;
    };

    RawValue value;
};

AIDL:

parcelable VehiclePropValue {

    long timestamp;

    int areaId;

    int prop;

    android.hardware.automotive.vehicle.VehiclePropertyStatus status = android.hardware.automotive.vehicle.VehiclePropertyStatus.AVAILABLE;

    android.hardware.automotive.vehicle.RawPropValues value;
}

parcelable RawPropValues {

    int[] int32Values = {};

    float[] floatValues;

    long[] int64Values;

    byte[] byteValues;

    @utf8InCpp 
    String stringValue;
}

parcelable VehiclePropValues {

    android.hardware.automotive.vehicle.VehiclePropValue[] payloads;

    long sharedMemoryId;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

VehiclePropertyStatus主要分为三种:

类型 含义
AVAILABLE 0x00 可读写
UNAVAILABLE 0x01 不可读写,表示某种车辆上从来不具有的属性
ERROR 0x02 属性出错

IVehicleCallback

HIDL:

interface IVehicleCallback {

    //订阅属性的回调
    oneway onPropertyEvent(vec<VehiclePropValue> propValues);

    
    //被订阅且SubscribeFlags::EVENTS_FROM_ANDROID == true 
    oneway onPropertySet(VehiclePropValue propValue);

    //属性设置错误时的回调
    oneway onPropertySetError(StatusCode errorCode,
                            int32_t propId,
                            int32_t areaId);
};

AIDL:

interface IVehicleCallback {
    //由于get,set返回都是通过回调,于是设置了onGetValues和onSetValues两个方法
    oneway void onGetValues(in android.hardware.automotive.vehicle.GetValueResults responses);

    oneway void onSetValues(in android.hardware.automotive.vehicle.SetValueResults responses);
    
    oneway void onPropertyEvent(in android.hardware.automotive.vehicle.VehiclePropValues propValues, int sharedMemoryFileCount);

    oneway void onPropertySetError(in android.hardware.automotive.vehicle.VehiclePropErrors errors);
}

(Get/Set)Value(Requests/Results) (only AIDL)

parcelable SetValueRequest {

    long requestId;

    android.hardware.automotive.vehicle.VehiclePropValue value;
}

parcelable SetValueRequests {

    android.hardware.automotive.vehicle.SetValueRequest[] payloads;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

parcelable SetValueResult {

    long requestId;

    android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK;
}

parcelable SetValueResults {

    android.hardware.automotive.vehicle.SetValueResult[] payloads;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

parcelable GetValueRequest {

    long requestId;

    android.hardware.automotive.vehicle.VehiclePropValue prop;
}

parcelable GetValueRequests {

    android.hardware.automotive.vehicle.GetValueRequest[] payloads;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

parcelable GetValueResult {

    long requestId;

    android.hardware.automotive.vehicle.StatusCode status = android.hardware.automotive.vehicle.StatusCode.OK;

    @nullable 
    android.hardware.automotive.vehicle.VehiclePropValue prop;
}

parcelable GetValueResults {

    android.hardware.automotive.vehicle.GetValueResult[] payloads;

    @nullable 
    ParcelFileDescriptor sharedMemoryFd;
}

SubscribeOptions

HIDL:

struct SubscribeOptions {
    int32_t propId;

    float sampleRate;

    SubscribeFlags flags;
};

enum SubscribeFlags : int32_t {
    UNDEFINED = 0x0,

    EVENTS_FROM_CAR = 0x1,

    EVENTS_FROM_ANDROID = 0x2,
};

AIDL:

parcelable SubscribeOptions {

    int propId;

    int[] areaIds;

    float sampleRate;
}

StatusCode

HIDL:

enum StatusCode : int32_t {
    OK = 0,

    TRY_AGAIN = 1,

    INVALID_ARG = 2,

    NOT_AVAILABLE = 3,

    ACCESS_DENIED = 4,

    INTERNAL_ERROR = 5,
};

AIDL:

enum StatusCode {
    OK = 0,
    TRY_AGAIN = 1,
    INVALID_ARG = 2,
    NOT_AVAILABLE = 3,
    ACCESS_DENIED = 4,
    INTERNAL_ERROR = 5,
    NOT_AVAILABLE_DISABLED = 6,
    NOT_AVAILABLE_SPEED_LOW = 7,
    NOT_AVAILABLE_SPEED_HIGH = 8,
    NOT_AVAILABLE_POOR_VISIBILITY = 9,
    NOT_AVAILABLE_SAFETY = 10,
}

差异对比

  • get/set: get和set在AIDL上统一通过IVehicleCallback返回, 于是在IVehicleCallback中新增了onGetValuesonSetValues方法,并新增了(get/set)Value(Request[s]/Result[s]),用于get和set请求。所有的StatusCode返回统一迁移到了(get/set)ValueResult中。
  • subscribe/unsubscribe: 在AIDL的subscribeOptions中,新增了int[] areaIds;字段并删除了subscribeFlags字段。对于AIDL实现来说,订阅可以具体到 (property id, area id) 上,而对于HIDL实现,订阅则只能针对property id。在AIDL上,unsubscribe支持一次取消多个订阅。

  • 对于VehiclePropConfigVehiclePropValue,AIDL实现都新增了VehiclePropConfigsVehiclePropValues,其中新增了字段ParcelFileDescriptor sharedMemoryFd;,用于共享内存。

Vhal架构

HIDL

classDiagram
IVehicle <|..VehicleHalManager
VehicleHalManager --> VehicleHal
VehicleHal <|.. XXXVehicleHal
VehicleHalManager --> SubscriptionManager
VehicleHal --> VehiclePropertyStore
XXXVehicleHal --> VehicleConnector
VehicleConnector <|.. XXXVehicleConnector
VehiclePropertyStore..>RecordConfig
VehiclePropertyStore..>RecordId
SubscriptionManager..>HalClient
SubscriptionManager..>HalClientVector
HalClientVector o.. HalClient

XXXVehicleHal --> RecurrentTimer

class IVehicle {
    + getAllConfigs() vec~VehiclePropConfig~*
    + getPropConfigs() StatusCode, vec~VehiclePropConfig~ *
    + get(VehicleProptyValue) VehicleProptyValue, StatusCode * 
    + set(VehiclePropValue) StatusCode* 
    + subscribe(IVehicleCallback, SubscribeOptions) StatusCode *
    + unsubscribe(IVehicleCallback, int) StatusCode *
}
<<interface>> IVehicle
class VehicleHalManager{
    - mHal
    - mSubscriptionManager
    - onHalEvent( recyclable_ptr~VehiclePropValue~)
    - onBatchHalEvent( vector~recyclable_ptr~VehiclePropValue~~)
}

class VehicleHal{
    - mPropStore
    - mOnHalEvent  
    + get(recyclable_ptr~VehiclePropValue~, StatusCode*) *
    + set(recyclable_ptr~VehiclePropValue~) StatusCode *
    + subscribe(int propId, int sampleRate) StatusCode *
    + doHalEvent(recyclable_ptr~VehiclePropValue~)
}
<<interface>> VehicleHal

class XXXVehicleHal{
    - mRecurrentTimer
    + onContinuousPropertyTimer(vector~int~ properties) 
}

class VehiclePropertyStore{
    - map~RecordId, VehiclePropValue~ mPropertyValues
    - map~int,RecordConfig~ mConfigs
    + registerProperty(VehiclePropConfig, TokenFunction)
    + readValuesForProperty(int) vector~VehiclePropValue~
    + getAllConfigs() vector~VehiclePropConfig~
    + writeValue(VehiclePropValue, bool updateStatus)
}

class RecordConfig{
    + VehiclePropConfig propConfig
    +  TokenFunction tokenFunction
}

class RecordId{
    + int prop
    + int area
    + int token
}

class SubscriptionManager{
    - map~int64_t, HalClient~ mClients
    - map~int, HalClientVector~ mPropToClients
    - map~int, SubscribeOptions~ mHalEventSubscribeOptions
    + addOrUpdateSubscription(int64_t, IVehicleCallback, hidl_vec~SubscribeOptions~, std::list~SubscribeOptions~)   
}

class HalClient{
    - map~int, SubscribeOptions~ mSubscriptions
    + addOrUpdateSubscription(SubscribeOptions) 
    + isSubscribed(int, SubscribeFlags)
}
class HalClientVector{
    + addOrUpdate(HalClient) 
}

class RecurrentTimer{
    - mCookieToEventsMap
    + registerRecurrentEvent(nanoseconds, int)
    + loop(action)
}

AIDL

classDiagram
BnVehicle <|..VehicleHal
VehicleHal --> IVehicleHardware
IVehicleHardware <|.. XXXVehicleHardware
VehicleHal --> SubscriptionManager
XXXVehicleHardware --> VehiclePropertyStore
VehiclePropertyStore ..> EventMode
VehiclePropertyStore ..> RecordId
VehiclePropertyStore ..> Record
Record ..> RecordId
XXXVehicleHardware --> RecurrentTimer

class BnVehicle {
    + getAllConfigs() VehiclePropConfigs*
    + getPropConfigs(int[])  VehiclePropConfigs *
    + get(IVehicleCallback, SetValueRequests) *
    + set(IVehicleCallback, GetValueRequests) *
    + subscribe(IVehicleCallback, SubscribeOptions[], int )*
    + unsubscribe(IVehicleCallback, int[]) *
}
<<interface>> BnVehicle

class VehicleHal {
    - mVehicleHardware
    - mGetValuesClients
    - mSetValuesClients
    - mConfigsByPropId
    - mSubscriptionManager
    - mRecurrentTimer
    + onPropertyChangeEvent(SubscriptionManager, vector~VehiclePropValue~) $
}

class SubscriptionManager{
    + subscribe(CallbackType, vector~SubscribeOptions~,bool isContinuousProperty) VhalResult~void~
    + unsubscribe(AIbinder* client, vector~int~ propIds) VhalResult~void~
    + getSubscribedClients(vector~VehiclePropValue~) unordered_map  IVehicleCallback\, vector ~VehiclePropValue\* ~
    
}

class IVehicleHardware{
    + getAllPropertyConfigs() *
    + setValues(SetValuesCallback, vector~SetValueRequest) StatusCode*
    + getValues(GetValuesCallback, vector~SetValueRequest) StatusCode* 
    + updateSampleRate(int, int, float) StatusCode* 
    + registerOnPropertyChangeEvent(PropertyChangeCallback) *  
}

<<interface>> IVehicleHardware

class XXXVehicleHardware{
    - mRecurrentTimer
    # mValuePool
    # mServerSidePropStore
    # getValue(VehiclePropValue)  ValueResult~RecyclableType~
    # setValue(VehiclePropValue) VhalResult~void~
}

class VehiclePropertyStore{
    - mRecordsByPropId
    - mOnValueChangeCallback
    + writeValue(RecyclableType, bool updateStatus, EventMode)
    + readValue(VehiclePropValue) VhalResult~RecyclableType~

} 

class RecordId{
    + area
    + token
}

class Record{
    + VehiclePropConfig propConfig
    + unordered_map<RecordId, RecyclableType> values
}

class EventMode{
    ON_VALUE_CHANGE
    ALWAYS
    NEVER
}
<<enumerate>> EventMode

class RecurrentTimer{
    - mCookieToEventsMap
    + registerRecurrentEvent(nanoseconds, int)
    + loop(action)
}