AndroidAutomotive模块介绍(四)VehicleHal介绍

前言

前面的文章中,描述了 Android Automotive 的框架中应用、Framework 层服务等知识,本篇文章将会继续按照 Android Automotive 框架介绍 Vehicle Hal 层服务的内容。

上一篇:AndroidAutomotive模块介绍(三)CarService服务

正文

1、VehicleHal 介绍

本篇文档将对 Andorid Automotive 框架中 VehicleHal 层展开介绍。VehicleHal 即为车辆硬件抽象层的定义。可以理解为 Android Automotive OS 中的硬件抽象层接口,包括车辆属性和方法;各厂商制造商会根据定义的 Hal 接口,实现定制化的模块服务。

VehicleHal 是链接 Android Automotive Car Services 与制造商实现车辆控制服务进程的桥梁,通过标准化接口对上层提供服务,对于服务的实现依赖厂商的定制化,可以忽略汽车制造商的具体实现,也就是说 CarService 调用 VehicleHal 定义的标准接口,厂商实现这些接口。

2、VehicleHal 模块功能

2.1 rc 文件

VehicleHal 的代码路径为:android/hardware/interfaces/automotive/vehicle/2.0/default。路径下有 android.hardware.automotive.vehicle@2.0-service.rc 文件,在开机阶段通过此 rc 文件,将 VehicleHal 进程启动,下面来看下 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

2.2 编译

对于 VehicleHal 的编译,可以对以下两个 Android.bp 文件介绍。

  • Hidl 接口编译
  • VehicleHal 服务编译

VehicleHal 定义的 Hal 接口编译介绍,Android.bp 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0,目录结构如下:

复制代码
ubuntu:android/hardware/interfaces/automotive/vehicle/2.0$ ls -l
total 132
-rw-r--r-- 1   users    375 Nov  9  2022 Android.bp
drwxrwxr-x 5   users   4096 Mar 22 13:55 default
-rw-r--r-- 1   users   2336 Nov  9  2022 IVehicleCallback.hal
-rw-r--r-- 1   users   3665 Nov  9  2022 IVehicle.hal
-rw-r--r-- 1   users 115184 Nov  9  2022 types.hal

下面是 Android.bp 文件的定义:

makefile 复制代码
// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "android.hardware.automotive.vehicle@2.0",
    root: "android.hardware",
    vndk: {
        enabled: true,
    },
    srcs: [
        "types.hal",
        "IVehicle.hal",
        "IVehicleCallback.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    gen_java: true,
}

编译文件中定义了 android.hardware.automotive.vehicle@2.0 HIDL 接口编译,包含三个文件 types.hal、IVehicle.hal、IVehicleCallback.hal 文件。

VehicleHal 服务编译介绍,Android.bp 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default,目录结构如下:

复制代码
ubuntu16:android/hardware/interfaces/automotive/vehicle/2.0/default$ ls -l
total 28
-rw-r--r-- 1   users 4705 Nov  9  2022 Android.bp
-rw-r--r-- 1   users  155 Nov  9  2022 android.hardware.automotive.vehicle@2.0-service.rc
drwxrwxr-x 4   users 4096 Jun  7  2022 common
drwxrwxr-x 3   users 4096 Jun  7  2022 impl
drwxrwxr-x 2   users 4096 Nov  9  2022 tests
-rw-r--r-- 1   users 1953 Nov  9  2022 VehicleService.cpp

Android.bp 文件定义如下:

makefile 复制代码
// Vehicle reference implementation lib
cc_library {
    name: "android.hardware.automotive.vehicle@2.0-manager-lib",
    vendor: true,
    defaults: ["vhal_v2_0_defaults"],
    srcs: [
        "common/src/Obd2SensorStore.cpp",
        "common/src/SubscriptionManager.cpp",
        "common/src/VehicleHalManager.cpp",
        "common/src/VehicleObjectPool.cpp",
        "common/src/VehiclePropertyStore.cpp",
        "common/src/VehicleUtils.cpp",
        "common/src/VmsUtils.cpp",
    ],
    local_include_dirs: ["common/include/vhal_v2_0"],
    export_include_dirs: ["common/include"],
}

// Vehicle default VehicleHAL implementation
cc_library_static {
    name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
    vendor: true,
    cflags: ["-Wno-unused-parameter", "-Wno-sign-compare"],
    defaults: ["vhal_v2_0_defaults"],
    srcs: [
        "impl/vhal_v2_0/CommConn.cpp",
        "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
        "impl/vhal_v2_0/VehicleEmulator.cpp",
        "impl/vhal_v2_0/PipeComm.cpp",
        "impl/vhal_v2_0/SocketComm.cpp",
        "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
        "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
    ],
    local_include_dirs: ["common/include/vhal_v2_0"],
    export_include_dirs: ["impl"],
    whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
    shared_libs: [
        "libbase",
        "libprotobuf-cpp-lite",
    ],
    static_libs: [
        "libjsoncpp",
        "libqemu_pipe",
        "android.hardware.automotive.vehicle@2.0-libproto-native",
    ],
}

cc_binary {
    name: "android.hardware.automotive.vehicle@2.0-service",
    defaults: ["vhal_v2_0_defaults"],
    init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
    vendor: true,
    relative_install_path: "hw",
    srcs: ["VehicleService.cpp"],
    shared_libs: [
        "libbase",
        "libprotobuf-cpp-lite",
    ],
    static_libs: [
        "android.hardware.automotive.vehicle@2.0-manager-lib",
        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
        "android.hardware.automotive.vehicle@2.0-libproto-native",
        "libjsoncpp",
        "libqemu_pipe",
    ],
}

从 Android.bp 的定义中,VehicleHal 的服务名为 android.hardware.automotive.vehicle@2.0-service,启动 rc 文件是 android.hardware.automotive.vehicle@2.0-service.rc,入口文件是 VehicleService.cpp,依赖自定义相关模块主要有 android.hardware.automotive.vehicle@2.0-manager-lib、android.hardware.automotive.vehicle@2.0-default-impl-lib、android.hardware.automotive.vehicle@2.0-libproto-native。

android.hardware.automotive.vehicle@2.0-manager-lib 模块是 common 目录下的文件所编译的内容,主要是 VehicleHal 所以来的模块。

android.hardware.automotive.vehicle@2.0-default-impl-lib 模块是 impl 目录下的文件所编译的内容,主要是 VehicleHal 的功能实现模块。

android.hardware.automotive.vehicle@2.0-libproto-native 模块是 impl/vhal_v2_0/proto 目录下的文件所编译的内容,目录下的文件为 VehicleHalProto.proto 文件,是一种序列化存储数据的方式。

2.3 HIDL 接口

Android Automotive 框架中 Hal 层接口文件有三个,IVehicle.hal、IVehicleCallback.hal 和 types.hal 文件。IVehicle.hal 文件中定义了 Vehicle Hal 对外提供的接口;IVehicleCallback.hal 文件中定义了 VehicleHal 的回调接口;types.hal 文件定义了 Vehicle Hal 的属性定义。

Hidl 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0。

2.3.1 IVehicle.hal

IVehicle.hal 文件中定义了 Vehicle Hal 对外提供的接口,上层 CarService 通过 IVehicle.hal 中定义的接口与 Vehicle Hal 通信。

复制代码
package android.hardware.automotive.vehicle@2.0;

import IVehicleCallback;

interface IVehicle {
  /**
   * Returns a list of all property configurations supported by this vehicle
   * HAL.
   * 返回此车辆HAL支持的所有属性配置的列表
   */
  getAllPropConfigs() generates (vec<VehiclePropConfig> propConfigs);

  /**
   * Returns a list of property configurations for given properties.
   *
   * If requested VehicleProperty wasn't found it must return
   * StatusCode::INVALID_ARG, otherwise a list of vehicle property
   * configurations with StatusCode::OK
   * 返回给定属性的属性配置列表。
   * 如果请求的车辆属性没有找到,它必须返回StatusCode::INVALID_ARG,否则返回一个车辆属性配置列表,StatusCode::OK
   */
  getPropConfigs(vec<int32_t> props)
          generates (StatusCode status, vec<VehiclePropConfig> propConfigs);

  /**
   * Get a vehicle property value.
   *
   * For VehiclePropertyChangeMode::STATIC properties, this method must always
   * return the same value always.
   * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
   * latest available value.
   *
   * Some properties like RADIO_PRESET requires to pass additional data in
   * GET request in VehiclePropValue object.
   *
   * If there is no data available yet, which can happen during initial stage,
   * this call must return immediately with an error code of
   * StatusCode::TRY_AGAIN.
   * 获取车辆属性值。
   * 对于 VehiclePropertyChangeMode::STATIC 的属性值,此方法会返回同一个值,不会改变。
   * 对于 VehiclePropertyChangeMode::ON_CHANGE 的属性值,此方法会返回最新值。
   */
  get(VehiclePropValue requestedPropValue)
          generates (StatusCode status, VehiclePropValue propValue);

  /**
   * Set a vehicle property value.
   *
   * Timestamp of data must be ignored for set operation.
   *
   * Setting some properties require having initial state available. If initial
   * data is not available yet this call must return StatusCode::TRY_AGAIN.
   * For a property with separate power control this call must return
   * StatusCode::NOT_AVAILABLE error if property is not powered on.
   * 设置车辆属性值。
   * 特殊场景:
   * 设置一些属性值需要其初始状态可用,如果初始状态不可用,需要返回 StatusCode::TRY_AGAIN。
   * 设置单独电源控制的属性,如果属性未上电,需要返回 StatusCode::TRY_AGAIN。
   */
  set(VehiclePropValue propValue) generates (StatusCode status);

  /**
   * Subscribes to property events.
   *
   * Clients must be able to subscribe to multiple properties at a time
   * depending on data provided in options argument.
   *
   * @param listener This client must be called on appropriate event.
   * @param options List of options to subscribe. SubscribeOption contains
   *                information such as property Id, area Id, sample rate, etc.
   * 订阅属性
   * 客户端可以一次订阅多个属性,这取决于 options 定义的参数。
   * 参数 SubscribeOptions 包含 属性id、区域id、采样率 等信息。
   */
  subscribe(IVehicleCallback callback, vec<SubscribeOptions> options)
          generates (StatusCode status);

  /**
   * Unsubscribes from property events.
   *
   * If this client wasn't subscribed to the given property, this method
   * must return StatusCode::INVALID_ARG.
   * 取消订阅属性
   * 如果客户端在此前没有对此属性进行订阅,则返回 StatusCode::INVALID_ARG。
   */
  unsubscribe(IVehicleCallback callback, int32_t propId)
          generates (StatusCode status);

  /**
   * Print out debugging state for the vehicle hal.
   *
   * The text must be in ASCII encoding only.
   *
   * Performance requirements:
   *
   * The HAL must return from this call in less than 10ms. This call must avoid
   * deadlocks, as it may be called at any point of operation. Any synchronization
   * primitives used (such as mutex locks or semaphores) must be acquired
   * with a timeout.
   *
   * 打印车辆的调试状态。
   */
  debugDump() generates (string s);
};
2.3.2 IVehicleCallback.hal

IVehicleCallback.hal 文件定义了 VehicleHal 的回调对象,上层 CarService 通过注册此回调对象以监听属性是否改变。VehicleHal 通过回调对象返回状态给到客户端。

复制代码
package android.hardware.automotive.vehicle@2.0;

interface IVehicleCallback {

    /**
     * Event callback happens whenever a variable that the API user has
     * subscribed to needs to be reported. This may be based purely on
     * threshold and frequency (a regular subscription, see subscribe call's
     * arguments) or when the IVehicle#set method was called and the actual
     * change needs to be reported.
     *
     * These callbacks are chunked.
     *
     * @param values that has been updated.
     * 当需要报告客户端订阅的变量时,就会调用此回调函数。
     * 这可能基于常规按频率上报或者客户端调用 IVehicle#set 函数时调用。
     */
    oneway onPropertyEvent(vec<VehiclePropValue> propValues);

    /**
     * This method gets called if the client was subscribed to a property using
     * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called.
     *
     * These events must be delivered to subscriber immediately without any
     * batching.
     *
     * @param value Value that was set by a client.
     * 如果客户端使用 SubscribeFlags::EVENTS_FROM_ANDROID 标志订阅属性,并且调用 IVehicle#set 函数,则回调此方法。
     */
    oneway onPropertySet(VehiclePropValue propValue);

    /**
     * Set property value is usually asynchronous operation. Thus even if
     * client received StatusCode::OK from the IVehicle::set(...) this
     * doesn't guarantee that the value was successfully propagated to the
     * vehicle network. If such rare event occurs this method must be called.
     *
     * @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
     * 设置属性通常是异步操作,客户端调用 IVehicle#set 函数到接收到 StatusCode::OK 的返回值,也不能保证此属性成功传播到车辆网络,如果发生这种低概率的事件,则回调此方法。
     * @ errorCode:StatusCode 枚举中的任何值。
     * @ property:发生错误的属性。
     * @ areaId:指定问题发生在哪个区域的位掩码,对于全局属性必须为 0。
     */
    oneway onPropertySetError(StatusCode errorCode,
                              int32_t propId,
                              int32_t areaId);
};
2.3.3 types.hal

types.hal 中定义了 VehicleHal 的属性、结构等数据。

2.3.3.1 车辆属性 VehiclePropertyType

下面列举 types.hal 中定义的 VehiclePropertyType 属性:

复制代码
package android.hardware.automotive.vehicle@2.0;

/**
 * Enumerates supported data type for VehicleProperty.
 * 枚举 VehicleProperty 支持的数据类型。
 * Used to create property ID in VehicleProperty enum.
 * 用于在 VehicleProperty enum 中创建属性 ID。
 */
enum VehiclePropertyType : int32_t { // VehicleProperty 的类型是 string、bool、还是 int32 等等
    STRING          = 0x00100000,
    BOOLEAN         = 0x00200000,
    INT32           = 0x00400000,
    INT32_VEC       = 0x00410000,
    INT64           = 0x00500000,
    INT64_VEC       = 0x00510000,
    FLOAT           = 0x00600000,
    FLOAT_VEC       = 0x00610000,
    BYTES           = 0x00700000,

    /**
     * Any combination of scalar or vector types. The exact format must be
     * provided in the description of the property.
     */
    MIXED           = 0x00e00000, // 这两个主要就是 VehicleProperty 用来进行或运算的。

    MASK            = 0x00ff0000
};
2.3.3.2 车辆区域属性 VehicleArea

下面是 types.hal 中定义的车辆区域属性:

复制代码
/**
 * Vehicle Areas
 * Used to construct property IDs in the VehicleProperty enum.
 * 用于在VehicleProperty enum中构造属性id。
 *
 * Some properties may be associated with particular vehicle areas. For
 * example, VehicleProperty:DOOR_LOCK property must be associated with
 * particular door, thus this property must be marked with
 * VehicleArea:DOOR flag.
 * 某些属性可能与特定车辆区域相关。例如,VehicleProperty:DOOR_LOCK 属性必须与特定的门相关联,因此该属性必须标记为 VehicleArea: door 标志。
 *
 * Other properties may not be associated with particular vehicle area,
 * these kind of properties must have VehicleArea:GLOBAL flag.
 * 其他属性可能不与特定的车辆区域相关联,这些属性必须具有VehicleArea:GLOBAL标志。
 *
 * [Definition] Area: An area represents a unique element of an AreaType.
 *   For instance, if AreaType is WINDOW, then an area may be FRONT_WINDSHIELD.
 *
 * [Definition] AreaID: An AreaID is a combination of one or more areas,
 *   and is represented using a bitmask of Area enums. Different AreaTypes may
 *   not be mixed in a single AreaID. For instance, a window area cannot be
 *   combined with a seat area in an AreaID.
 *
 * Rules for mapping a zoned property to AreaIDs:
 *  - A property must be mapped to an array of AreaIDs that are impacted when
 *    the property value changes.
 *  - Each element in the array must represent an AreaID, in which, the
 *    property value can only be changed together in all the areas within
 *    an AreaID and never independently. That is, when the property value
 *    changes in one of the areas in an AreaID in the array, then it must
 *    automatically change in all other areas in the AreaID.
 *  - The property value must be independently controllable in any two
 *    different AreaIDs in the array.
 *  - An area must only appear once in the array of AreaIDs. That is, an
 *    area must only be part of a single AreaID in the array.
 *
 * [Definition] Global Property: A property that applies to the entire car
 *   and is not associated with a specific area. For example, FUEL_LEVEL,
 *   HVAC_STEERING_WHEEL_HEAT.
 *
 * Rules for mapping a global property to AreaIDs:
 *  - A global property must not be mapped to AreaIDs.
*/
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, // 车轮区域
    YFVehicleAreaTire = 0x08000000,
    MASK        = 0x0f000000,
};
2.3.3.3 车辆属性分组类型 VehiclePropertyGroup

下面是 types.hal 中定义的车辆属性分组类型:

复制代码
/**
 * Enumerates property groups.
 * 车辆属性分组枚举
 *
 * Used to create property ID in VehicleProperty enum.
 * 用于在VehicleProperty enum中创建属性ID。
 */
enum VehiclePropertyGroup : int32_t { // AndroidO 之后的 treble,用于区分 android 原生的 property 和厂商的 property。
    /**
     * Properties declared in AOSP must use this flag.
     * AOSP 原生的属性标志
     */
    SYSTEM      = 0x10000000,

    /**
     * Properties declared by vendors must use this flag.
     * 厂商自定义的属性标志
     */
    VENDOR      = 0x20000000,

    MASK        = 0xf0000000,
};
2.3.3.4 车辆属性 VehicleProperty

下面是 types.hal 中定义的车辆属性

复制代码
/**
 * Declares all vehicle properties. VehicleProperty has a bitwise structure.
 * Each property must have:
 *  - a unique id from range 0x0100 - 0xffff
 *  - associated data type using VehiclePropertyType
 *  - property group (VehiclePropertyGroup)
 *  - vehicle area (VehicleArea)
 *
 * Vendors are allowed to extend this enum with their own properties. In this
 * case they must use VehiclePropertyGroup:VENDOR flag when property is
 * declared.
 *
 * When a property's status field is not set to AVAILABLE:
 *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
 *  - IVehicle#get is not guaranteed to work.
 *
 * Properties set to values out of range must be ignored and no action taken
 * in response to such ill formed requests.
 */
enum VehicleProperty : int32_t {

    /** Undefined property. */
    INVALID = 0x00000000,

    /**
     * VIN of vehicle
     * 车辆 VIN 码
     *
     * @change_mode VehiclePropertyChangeMode:STATIC
     * @access VehiclePropertyAccess:READ
     */
    INFO_VIN = (
        0x0100
        | VehiclePropertyGroup:SYSTEM // 原生属性
        | VehiclePropertyType:STRING // 属性值是 String 类型
        | VehicleArea:GLOBAL), // 全局属性

    /**
     * Model of vehicle
     * 车辆型号
     *
     * @change_mode VehiclePropertyChangeMode:STATIC
     * @access VehiclePropertyAccess:READ
     */
    INFO_MODEL = (
        0x0102
        | VehiclePropertyGroup:SYSTEM // 原生属性
        | VehiclePropertyType:STRING // 属性值是 String 类型
        | VehicleArea:GLOBAL), // 全局属性
...
};
2.3.3.5 车辆座位占用状态 VehicleSeatOccupancyState

下面是 types.hal 中定义的车辆座位占用状态值

复制代码
/**
 * Used by seat occupancy to enumerate the current occupancy state of the seat.
 * 由座位占用使用,以枚举座位的当前占用状态
 */
enum  VehicleSeatOccupancyState : int32_t {

    UNKNOWN = 0,
    VACANT = 1, // 空闲
    OCCUPIED = 2 // 占用
};
2.3.3.6 灯光状态属性 VehicleLightState

下面是 types.hal 中定义的灯光状态属性

复制代码
/**
 * Used by lights state properties to enumerate the current state of the lights.
 * 由灯光状态属性使用,枚举灯光的当前状态。
 * Most XXX_LIGHTS_STATE properties will only report ON and OFF states.  Only
 * the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
 * 大多数 XXX_LIGHTS_STATE 属性将只报告 ON 和 OFF 状态。只有 headlight_state 属性会报告 DAYTIME_RUNNING。
 */
enum  VehicleLightState : int32_t {

    OFF = 0,
    ON = 1,
    DAYTIME_RUNNING = 2
};
2.3.3.7 车灯开关属性 VehicleLightSwitch

下面是 types.hal 中定义的车灯开关属性

复制代码
/**
 * Used by lights switch properties to enumerate user selected switch setting.
 * 由灯开关属性使用,枚举用户选择的开关设置。
 * XXX_LIGHTS_SWITCH properties report the switch settings that the user
 * selects.  The switch setting may be decoupled from the state reported if the
 * user selects AUTOMATIC.
 * XXX_LIGHTS_SWITCH 属性报告用户选择的开关设置。如果用户选择 AUTOMATIC,开关设置可能与报告的状态分离。
 */
enum VehicleLightSwitch : int32_t {
    OFF = 0,
    ON = 1,
    /**
     * Daytime running lights mode.  Most cars automatically use DRL but some
     * cars allow the user to activate them manually.
     * 日间行车灯模式。大多数汽车自动使用DRL,但有些汽车允许用户手动激活它们。
     */
    DAYTIME_RUNNING = 2,
    /**
     * Allows the vehicle ECU to set the lights automatically
     * 允许车辆ECU自动设置灯光
     */
    AUTOMATIC = 0x100,
};
2.3.3.8 车辆充电连接线类型 EvConnectorType

下面是 types.hal 中定义的车辆充电连接线类型属性

复制代码
/**
 * Used by INFO_EV_CONNECTOR_TYPE to enumerate the type of connectors
 * available to charge the vehicle.
 * 由 INFO_EV_CONNECTOR_TYPE 使用,枚举可用于给车辆充电的连接器类型。
 */
enum EvConnectorType : int32_t {
    /**
     * Default type if the vehicle does not know or report the EV connector
     * type.
     * 如果车辆不知道或不报告EV连接器类型,则默认类型
     */
    UNKNOWN = 0,
    IEC_TYPE_1_AC = 1,              // aka Yazaki
    IEC_TYPE_2_AC = 2,              // aka Mennekes
    IEC_TYPE_3_AC = 3,              // aka Scame
    IEC_TYPE_4_DC = 4,              // aka CHAdeMO
    IEC_TYPE_1_CCS_DC = 5,          // aka Combo 1
    IEC_TYPE_2_CCS_DC = 6,          // aka Combo 2
    TESLA_ROADSTER = 7,
    TESLA_HPWC = 8,
    TESLA_SUPERCHARGER = 9,
    GBT_AC = 10,
    GBT_DC = 11,

    /**
     * Connector type to use when no other types apply. Before using this
     * value, work with Google to see if the EvConnectorType enum can be
     * extended with an appropriate value.
     */
    OTHER = 101,
};
2.3.3.9 端口位置属性 PortLocationType

下面是 types.hal 中定义的用于枚举燃油门或燃油口位置属性。

复制代码
/**
 * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or
 * ev port location.
 * 用于描述 INFO_FUEL_DOOR_LOCATION 和 INFO_CHARGE_PORT_LOCATION 信号的燃油门或燃油口位置。
 */
enum PortLocationType : int32_t {
    /**
     * Default type if the vehicle does not know or report the Fuel door
     * and ev port location.
     */
    UNKNOWN = 0,
    FRONT_LEFT = 1,
    FRONT_RIGHT = 2,
    REAR_RIGHT = 3,
    REAR_LEFT = 4,
    FRONT = 5,
    REAR = 6,
};
2.3.3.10 风扇方向属性 VehicleHvacFanDirection

下面是 types.hal 中定义的风扇方向属性。

复制代码
/**
 * Bit flags for fan direction
 * 风扇方向的位标志
 */
enum VehicleHvacFanDirection : int32_t {
    FACE = 0x1,
    FLOOR = 0x2,
    DEFROST = 0x4,
};
2.3.3.11 车辆油量属性 VehicleOilLevel

下面是 types.hal 中定义的车辆油量属性。

复制代码
enum VehicleOilLevel : int32_t {
    /**
     * Oil level values
     */
    CRITICALLY_LOW = 0,
    LOW = 1,
    NORMAL = 2,
    HIGH = 3,
    ERROR = 4,
};
2.3.3.12 车辆输入事件属性 VehicleHwKeyInputAction

下面是 types.hal 中定义的车辆输入事件属性。

复制代码
enum VehicleHwKeyInputAction : int32_t {
    /** Key down */
    ACTION_DOWN = 1, // 输入事件按下

    /** Key up */
    ACTION_UP = 0, // 输入事件抬起
};
2.3.3.13 车辆属性修改模式 VehiclepropertyChangeMode

下面是 types.hal 中定义的属性是否可以改变的配置。

复制代码
/**
 * This describes how value of property can change.
 * 描述属性是否可以改变
 */
enum VehiclePropertyChangeMode : int32_t {
    /**
     * Property of this type must never be changed. Subscription is not supported
     * for these properties.
     * STATIC 表示属性不可修改
     */
    STATIC = 0x00,

    /**
     * Properties of this type must report when there is a change.
     * IVehicle#get call must return the current value.
     * Set operation for this property is assumed to be asynchronous. When the
     * property is read (using IVehicle#get) after IVehicle#set, it may still
     * return old value until underlying H/W backing this property has actually
     * changed the state. Once state is changed, the property must dispatch
     * changed value as event.
     * ON_CHANGE 表示属性必须在改变时报告
     */
    ON_CHANGE = 0x01,

    /**
     * Properties of this type change continuously and require a fixed rate of
     * sampling to retrieve the data.  Implementers may choose to send extra
     * notifications on significant value changes.
     * CONTINUOUS 属性在不断变化,需要固定的速率来检索数据
     */
    CONTINUOUS = 0x02,
};
2.3.3.14 车辆属性访问 VehiclePropertyAccess

下面是 types.hal 中定义的车辆属性访问配置。

复制代码
/**
 * Property config defines the capabilities of it. User of the API
 * must first get the property config to understand the output from get()
 * commands and also to ensure that set() or events commands are in sync with
 * the expected output.
 * 属性定义功能访问模式。
 */
enum VehiclePropertyAccess : int32_t {
    NONE = 0x00,

    READ = 0x01, // 只读
    WRITE = 0x02, // 只写
    READ_WRITE = 0x03, // 读写
};
2.3.3.15 车辆属性状态 VehiclePropertyStatus

下面是 types.hal 中定义的车辆属性状态。

复制代码
/**
 * Property status is a dynamic value that may change based on the vehicle state.
 * 属性状态是一个动态值,可能会根据车辆状态而改变。
 */
enum VehiclePropertyStatus : int32_t {
    /** Property is available and behaving normally */
    AVAILABLE   = 0x00, // 属性可用且运行正常
    /**
     * A property in this state is not available for reading and writing.  This
     * is a transient state that depends on the availability of the underlying
     * implementation (e.g. hardware or driver). It MUST NOT be used to
     * represent features that this vehicle is always incapable of.  A get() of
     * a property in this state MAY return an undefined value, but MUST
     * correctly describe its status as UNAVAILABLE A set() of a property in
     * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
     * the value of the status field when writing a property value coming from
     * Android.
     */
    UNAVAILABLE = 0x01, // 处于此状态的属性不可用于读写。这是一种瞬态,依赖于底层实现的可用性(例如硬件或驱动程序)。
    /** There is an error with this property. */
    ERROR       = 0x02,
};
2.3.3.16 汽车齿轮属性 VehicleGear

下面是 types.hal 中定义的汽车齿轮属性。

复制代码
/**
 * Various gears which can be selected by user and chosen in system.
 * 各种齿轮可由用户选择,并在系统中选择。
 */
enum VehicleGear : int32_t {
    GEAR_NEUTRAL = 0x0001,
    GEAR_REVERSE = 0x0002,
    GEAR_PARK = 0x0004,
    GEAR_DRIVE = 0x0008,
    GEAR_1 = 0x0010,
    GEAR_2 = 0x0020,
    GEAR_3 = 0x0040,
    GEAR_4 = 0x0080,
    GEAR_5 = 0x0100,
    GEAR_6 = 0x0200,
    GEAR_7 = 0x0400,
    GEAR_8 = 0x0800,
    GEAR_9 = 0x1000,
};
2.3.3.17 汽车座椅区域属性 VehicleAreaSeat

下面是 types.hal 中定义的汽车座椅区域属性。

复制代码
/**
 * Various Seats in the car.
 * 汽车里的各种座位。
 */
enum VehicleAreaSeat : int32_t {
    ROW_1_LEFT   = 0x0001,
    ROW_0_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
};
2.3.3.18 汽车玻璃区域属性 VehicleAreaWindow

下面是 types.hal 中定义的汽车玻璃区域属性。

复制代码
/**
 * 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,

};
2.3.3.19 车辆门区域属性 VehicleAreaDoor

下面是 types.hal 中定义的车辆门区域属性。

复制代码
enum VehicleAreaDoor : int32_t {
    ROW_1_LEFT = 0x00000001,
    ROW_1_RIGHT = 0x00000004,
    ROW_2_LEFT = 0x00000010,
    ROW_2_RIGHT = 0x00000040,
    ROW_3_LEFT = 0x00000100,
    ROW_3_RIGHT = 0x00000400,
    HOOD = 0x10000000,
    REAR = 0x20000000,
};
2.3.3.20 车辆镜子区域属性 VehicleAreaMirror

下面是 types.hal 中定义的车辆镜子区域属性。

复制代码
enum VehicleAreaMirror : int32_t {
    DRIVER_LEFT = 0x00000001,
    DRIVER_RIGHT = 0x00000002,
    DRIVER_CENTER = 0x00000004,
};
2.3.3.21 车辆转向灯属性 VehicleTurnSignal

下面是 types.hal 中定义的车辆转向灯属性。

复制代码
enum VehicleTurnSignal : int32_t {
    NONE = 0x00,
    RIGHT = 0x01,
    LEFT = 0x02,
};
2.3.3.22 车辆区域配置结构体 VehicleAreaConfig

下面是 types.hal 中定义的车辆区域配置结构体。

复制代码
struct VehicleAreaConfig {
    /**
     * Area id is ignored for VehiclePropertyGroup:GLOBAL properties.
     * 对于全局属性,忽略 Area 区域 id。
     */
    int32_t areaId;

    /**
     * If the property has @data_enum, leave the range to zero.
     *
     * Range will be ignored in the following cases:
     *    - The VehiclePropertyType is not INT32, INT64 or FLOAT.
     *    - Both of min value and max value are zero.
     */

    int32_t minInt32Value;
    int32_t maxInt32Value;

    int64_t minInt64Value;
    int64_t maxInt64Value;

    float minFloatValue;
    float maxFloatValue;
};
2.3.3.23 车辆属性配置 VehiclePropConfig

下面是 types.hal 中定义的车辆属性配置。

复制代码
struct VehiclePropConfig { // Vehicle Property 的配置
    /** Property identifier */
    int32_t prop; // property 标识符

    /**
     * Defines if the property is read or write or both.
     */
    VehiclePropertyAccess access; // 定义属性是读还是写,还是两者兼而有之

    /**
     * Defines the change mode of the property.
     */
    VehiclePropertyChangeMode changeMode; // 定义属性的更改模式

    /**
     * Contains per-area configuration.
     */
    vec<VehicleAreaConfig> areaConfigs; // 包含每个区域的配置

    /** Contains additional configuration parameters */
    vec<int32_t> configArray; // 包含其他配置参数

    /**
     * Some properties may require additional information passed over this
     * string. Most properties do not need to set this.
     */
    string configString; // 某些属性可能需要通过该字符串传递额外的信息

    /**
     * Min sample rate in Hz.
     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
     */
    float minSampleRate; // 最小采样率(Hz)

    /**
     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
     * Max sample rate in Hz.
     */
    float maxSampleRate; // 最大采样率(Hz)
};
2.3.3.24 车辆属性值 VehiclePropValue

下面是 types.hal 中定义的车辆属性值。

复制代码
/**
 * Encapsulates the property name and the associated value. It
 * is used across various API calls to set values, get values or to register for
 * events.
 * 封装属性名和关联值。它在各种 API 调用中用于设置值、获取值或注册事件。
 */
struct VehiclePropValue {
    /** Time is elapsed nanoseconds since boot */
    int64_t timestamp; // 从 boot 开始的时间

    /**
     * Area type(s) for non-global property it must be one of the value from
     * VehicleArea* enums or 0 for global properties.
     * 对于非全局属性,区域类型必须是VehicleArea*枚举中的值之一;对于全局属性必须是0。
     */
    int32_t areaId;

    /** Property identifier */
    int32_t prop; // 属性标识符

    /** Status of the property */
    VehiclePropertyStatus status; // 属性状态

    /**
     * Contains value for a single property. Depending on property data type of
     * this property (VehiclePropetyType) one field of this structure must be filled in.
     * 包含单个属性的值。根据该属性的属性数据类型(vehiclepetytype),必须填充该结构的一个字段。
     */
    struct RawValue {
        /**
         * This is used for properties of types VehiclePropertyType#INT
         * and VehiclePropertyType#INT_VEC
         */
        vec<int32_t> int32Values;

        /**
         * This is used for properties of types VehiclePropertyType#FLOAT
         * and VehiclePropertyType#FLOAT_VEC
         */
        vec<float> floatValues;

        /** This is used for properties of type VehiclePropertyType#INT64 */
        vec<int64_t> int64Values;

        /** This is used for properties of type VehiclePropertyType#BYTES */
        vec<uint8_t> bytes;

        /** This is used for properties of type VehiclePropertyType#STRING */
        string stringValue;
    };

    RawValue value;
};

2.4 启动流程

2.4.1 VehicleHal 类图

下面是 VehicleHal 的类图

2.4.2 VehicleHal 启动序列图

下面是 VehicleHal 启动序列图

2.4.3 VehicleHal 启动流程
2.4.3.1 VehicleService.cpp

VehicleHal 的入口文件是 VehicleService.cpp。路径为:android/hardware/interfaces/automotive/vehicle/2.0/default。下面是 VehicleService.cpp 的内容:

cpp 复制代码
#define LOG_TAG "automotive.vehicle@2.0-service"
#include <android/log.h>
#include <hidl/HidlTransportSupport.h>

#include <iostream>

#include <vhal_v2_0/VehicleHalManager.h>
#include <vhal_v2_0/EmulatedVehicleHal.h>

using namespace android;
using namespace android::hardware;
using namespace android::hardware::automotive::vehicle::V2_0;

int main(int /* argc */, char* /* argv */ []) {
    // 创建 VehiclePropertyStore 对象
    auto store = std::make_unique<VehiclePropertyStore>();
    // 创建 EmulatedVehicleHal 对象
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
    // 创建 VehicleEmulator 对象
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    // 创建 VehicleHalManager 对象
    auto service = std::make_unique<VehicleHalManager>(hal.get());

    configureRpcThreadpool(4, true /* callerWillJoin */);

    // 注册 VehicleService 服务
    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;
}

从 VehicleService.cpp 中可以发现,主要初始化了 Vehicle 相关服务类,并注册 Vehicle 服务。下面可以来简单跟踪下各类的功能。

2.4.3.2 VehiclePropertyStore.cpp

VehiclePropertyStore 类是用于封装与存储和访问配置、存储和修改车辆属性值相关的工作。内部主要维护一个 PropertyMap mPropertyValues,PropertyMap = std::map<RecordId, VehiclePropValue>;用于通过 RecordId 保存对应的 VehiclePropValue 值。

VehiclePropValue.h :

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

VehiclePropertyStore.cpp :

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

车辆属性在 VehiclePropertyStore 是存储在有序的 Map 集合中,这样可以更加方便的获取属性的值。VehiclePropertyStore 的使用是线程安全的,方法间使用同步阻塞保证线程安全。

下面是 VehiclePropertyStore.h 头文件的内容:

cpp 复制代码
class VehiclePropertyStore {
public:
    /* Function that used to calculate unique token for given VehiclePropValue */
    using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;

private:
    // 定义 RecordConfig 结构体
    struct RecordConfig {
        VehiclePropConfig propConfig;
        TokenFunction tokenFunction;
    };

    // 定义 RecordId 结构体
    struct RecordId {
        int32_t prop; // propid
        int32_t area; // areaid
        int64_t token;

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

    // 定义 RecordId 和 vehiclePropValue 对应的 Map 集合
    using PropertyMap = std::map<RecordId, VehiclePropValue>;
    using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>;

public:
    // 注册 Property 函数
    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. */
    // 写入 VehiclePropValue 值
    bool writeValue(const VehiclePropValue& propValue, bool updateStatus);

    // 移除 VehiclePropValue 值
    void removeValue(const VehiclePropValue& propValue);
    // 通过 propId 移除 VehiclePropValue 值
    void removeValuesForProperty(int32_t propId);

    // 获取所有的 VehiclePropValue 值
    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;

    // 获取所有的 VehiclePropConfig 值
    std::vector<VehiclePropConfig> getAllConfigs() const;
    // 根据 propId 获取 VehiclePropConfig 值
    const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
    const VehiclePropConfig* getConfigOrDie(int32_t propId) const;

private:
    RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const;
    const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const;
    PropertyMapRange findRangeLocked(int32_t propId) const;

private:
    using MuxGuard = std::lock_guard<std::mutex>;
    mutable std::mutex mLock;
    std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;

    PropertyMap mPropertyValues;  // Sorted map of RecordId : VehiclePropValue.
};
2.4.3.3 EmulatedVehicleHal

EmulatedVehicleHal 的文件路径如下:

EmulatedVehicleHal.h 路径为:

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

EmulatedVehicleHal.cpp 路径为:

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

EmulatedVehicleHal 可以理解为 VehicleHal 功能的真正实施类,EmulatedVehicleHal 实现了 EmulatedVehicleHalIface 和 VehicleHal 的功能。上层的 Binder 在 Hal 层的流转后,最终是通过 EmulatedVehicleHal 去处理的。下面是 EmulatedVehicleHal 头文件的内容:

cpp 复制代码
class EmulatedVehicleHal : public EmulatedVehicleHalIface { // EmulatedVehicleHalIface 继承了 VehicleHal
public:
    EmulatedVehicleHal(VehiclePropertyStore* propStore);
    ~EmulatedVehicleHal() = default;
    
    //  Methods from VehicleHal
    // 实现了 VehicleHal 接口功能,上层的 Binder 调用会调用到这里
    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;

    //  Methods from EmulatedVehicleHalIface
    // 实现了 EmulatedVehicleHalIface 接口功能
    bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
    std::vector<VehiclePropValue> getAllProperties() const override;
    
private:
    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
    }   
    
    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
    void onFakeValueGenerated(const VehiclePropValue& value);
    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                             int32_t targetDisplay); 
                                             
    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
    bool isContinuousProperty(int32_t propId) const;
    void initStaticConfig();
    void initObd2LiveFrame(const VehiclePropConfig& propConfig);
    void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
    StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
                                   VehiclePropValue* outValue);
    StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);

    /* Private members */
    VehiclePropertyStore* mPropStore;
    std::unordered_set<int32_t> mHvacPowerProps;
    RecurrentTimer mRecurrentTimer;
    GeneratorHub mGeneratorHub;
};
2.4.3.4 VehicleEmulator

VehicleEmulator 的文件路径如下:

VehicleEmulator.h 的文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h

VehicleEmulator.cpp 的文件路径为:

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

VehicleEmulator 的解释是通过 ADB 或 Pipe 从主机端提供控制接口来模拟车辆。

VehicleEmulator 可以理解为通过 SPI 通信与 MCU 芯片建立通信,连通车身 Can 网络来获取车辆的信号的处理类。厂商基于 VehicleEmulator 的功能搭建厂商自身的车身通信功能,例如通过 DBus 与 MCU 通信,获取来自 MCU 的车身数据;MCU 通过 Can 网络获取车身其他固件,例如空调、座椅等其他 ECU 件的数据。

下面是 VehicleEmulator.h 文件的内容:

cpp 复制代码
class VehicleEmulator;  // Forward declaration.

/** Extension of VehicleHal that used by VehicleEmulator. */
// 定义 EmulatedVehicleHalIface 类,扩展 VehicleHal 接口。
class EmulatedVehicleHalIface : public VehicleHal {
public:
    virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
    virtual std::vector<VehiclePropValue> getAllProperties() const = 0;

    void registerEmulator(VehicleEmulator* emulator) {
        ALOGI("%s, emulator: %p", __func__, emulator);
        std::lock_guard<std::mutex> g(mEmulatorLock);
        mEmulator = emulator;
    }

protected:
    VehicleEmulator* getEmulatorOrDie() {
        std::lock_guard<std::mutex> g(mEmulatorLock);
        if (mEmulator == nullptr) abort();
        return mEmulator;
    }

private:
    mutable std::mutex mEmulatorLock;
    VehicleEmulator* mEmulator;
};

/**
 * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
 */
// 定义 VehicleEmulator 类,通过 socket、pipe 模拟车辆
class VehicleEmulator : public MessageProcessor {
   public:
    VehicleEmulator(EmulatedVehicleHalIface* hal);
    virtual ~VehicleEmulator();

    void doSetValueFromClient(const VehiclePropValue& propValue);
    void processMessage(emulator::EmulatorMessage const& rxMsg,
                        emulator::EmulatorMessage& respMsg) override;

   private:
    friend class ConnectionThread;
    using EmulatorMessage = emulator::EmulatorMessage;

    void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
    void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
    void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
    void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
    void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
    void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
                                    const VehiclePropConfig& cfg);
    void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
                                       const VehiclePropValue* val);

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

VehicleHalManager 的文件路径如下:

VehicleHalManager.h 文件路径为:android/hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h

VehicleHalManager.cpp 文件路径为:

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

VehicleHalManager 类是 IVehicle HIDL 接口和厂商实现之间的一个代理。VehicleHalManager 直接继承了 IVehicle,上层调用 Hild 接口时,会最先调用到此类中,VehicleHalManager 在初始化时获取 VehicleHal 对象,厂商需要实现 VehicleHal 类以提供 VehicleHal 的功能。

下面是 VehicleHalManager.h 文件的内容:

cpp 复制代码
/**
 * This class is a thick proxy between IVehicle HIDL interface and vendor's implementation.
 *
 * It has some boilerplate code like batching and caching property values, checking permissions,
 * etc. Vendors must implement VehicleHal class.
 */
// VehicleHalManager 继承 IVehicle 类,提供 Hidl 接口调用
class VehicleHalManager : public IVehicle {
public:
    // 构造函数需要传入 VehicleHal 类对象,具体 Hidl 接口功能实现由 VehicleHal 提供
    VehicleHalManager(VehicleHal* vehicleHal)
        : mHal(vehicleHal),
          mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
                                         this, std::placeholders::_1)) {
        init();
    }

    virtual ~VehicleHalManager();

    void init();

    // ---------------------------------------------------------------------------------------------
    // Methods derived from IVehicle 实现 Hidl 接口函数
    Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb)  override;
    Return<void> getPropConfigs(const hidl_vec<int32_t>& properties,
                                getPropConfigs_cb _hidl_cb)  override;
    Return<void> get(const VehiclePropValue& requestedPropValue,
                     get_cb _hidl_cb)  override;
    Return<StatusCode> set(const VehiclePropValue& value)  override;
    Return<StatusCode> subscribe(const sp<IVehicleCallback>& callback,
                                const hidl_vec<SubscribeOptions>& options)  override;
    Return<StatusCode> unsubscribe(const sp<IVehicleCallback>& callback,
                                   int32_t propId)  override;
    Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override;

private:
    using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
    // Returns true if needs to call again shortly.
    using RetriableAction = std::function<bool()>;

    // ---------------------------------------------------------------------------------------------
    // Events received from VehicleHal
    void onHalEvent(VehiclePropValuePtr  v);
    void onHalPropertySetError(StatusCode errorCode, int32_t property,
                               int32_t areaId);

    // ---------------------------------------------------------------------------------------------
    // This method will be called from BatchingConsumer thread
    void onBatchHalEvent(const std::vector<VehiclePropValuePtr >& values);

    void handlePropertySetEvent(const VehiclePropValue& value);

    const VehiclePropConfig* getPropConfigOrNull(int32_t prop) const;

    bool checkWritePermission(const VehiclePropConfig &config) const;
    bool checkReadPermission(const VehiclePropConfig &config) const;
    void onAllClientsUnsubscribed(int32_t propertyId);

    static bool isSubscribable(const VehiclePropConfig& config,
                               SubscribeFlags flags);
    static bool isSampleRateFixed(VehiclePropertyChangeMode mode);
    static float checkSampleRate(const VehiclePropConfig& config,
                                 float sampleRate);
    static ClientId getClientId(const sp<IVehicleCallback>& callback);
private:
    VehicleHal* mHal;  // 保存 VehicleHal 对象
    std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
    SubscriptionManager mSubscriptionManager;

    hidl_vec<VehiclePropValue> mHidlVecOfVehiclePropValuePool;

    ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
    BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer;
    VehiclePropValuePool mValueObjectPool;
};

3、总结

本篇主要描述了 Android 原生的 Automotive 框架中 VehicleHal 的逻辑。简单来说,VehicleHal 层主要是完成了对上层 Hidl 接口功能的实现,具体实现依赖厂商的逻辑,从框架上是封装了厂商的 VechielHal 实现,提供车辆网络信号的设置和获取功能。

上一篇:AndroidAutomotive模块介绍(三)CarService服务

相关推荐
雨白1 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹3 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空5 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭5 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日6 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安6 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑6 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟10 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡12 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0012 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体