Android Automotive VehicleService

Posted 探求之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Automotive VehicleService相关的知识,希望对你有一定的参考价值。

android Automotive(七) VehicleService

VehicleService 是Android Automotive在硬件抽象层的一个核心native服务。处理和车辆相关功能,为系统提供获取车身信息以及设置相关状态的接口。

HAL接口

从Android O (8.0) 开始,Google推出了HIDL架构,HIDL定义的接口以.hal为后缀名。

定义了三个HIDL接口文件。

文件说明
IVehicle.hal接口定义
IVehicleCallback.hal回调接口使用的数据结构
types.hal车辆属性和数据定义

IVehicle

定义了Android Automtive在硬件抽象层和系统框架层的接口。实际也支持硬件抽象层-硬件抽象层、系统框架层-系统框架层的通信。

IVehicle代码路径:hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal

package android.hardware.automotive.vehicle@2.0;

import IVehicleCallback;

interface IVehicle 
  /**
   * Returns a list of all property configurations supported by this vehicle
   * 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
   */
  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.
   */
  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.
   */
  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.
   */
  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.
   */
  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);
;
接口名称
getAllPropConfigs() generates (vec propConfigs);获取全部车辆属性配置
getPropConfigs(vec<int32_t> props) generates (StatusCode status, vec propConfigs);获取一个车辆属性配置
get(VehiclePropValue requestedPropValue) generates (StatusCode status, VehiclePropValue propValue);获取一个车辆属性值
set(VehiclePropValue propValue) generates (StatusCode status);设置一个车辆属性值
subscribe(IVehicleCallback callback, vec options) generates (StatusCode status);订阅一个车辆属性变化
unsubscribe(IVehicleCallback callback, int32_t propId) generates (StatusCode status);取消订阅一个车辆属性变化
debugDump() generates (string s);dump信息

IVehicleCallback

回调接口使用的数据结构

代码路径:

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

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.
     */
    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.
     */
    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
     */
    oneway onPropertySetError(StatusCode errorCode,
                              int32_t propId,
                              int32_t areaId);
;
oneway onPropertyEvent(vec propValues);车辆属性变化通知
oneway onPropertySet(VehiclePropValue propValue);车辆属性设置通知
oneway onPropertySetError(StatusCode errorCode, int32_t propId, int32_t areaId);车辆属性设置错误通知

types.hal

车辆属性和数据定义。

代码路径:hardware/interfaces/automotive/vehicle/2.0/types.hal

VehiclePropertyTypeenum
VehicleAreaenum
VehiclePropertyGroupenum
VehiclePropertyenum
VehicleVendorPermissionenum
VehiclePropertyChangeModeenum
VehiclePropertyAccessenum
VehiclePropertyStatusenum
VehicleAreaSeatenum
VehicleAreaWindowenum
VehicleAreaDoorenum
VehicleAreaMirrorenum
VehicleAreaWheelenum
VehicleAreaConfigstruct
VehiclePropConfigstruct
VehiclePropValuestruct

编译模块

Android Automotive在硬件抽象层提供了很多模块,来支持系统编译和运行。

Module
android.hardware.automotive.vehicle@2.0
vhal_v2_0_defaults
vhal_v2_0_target_defaults
android.hardware.automotive.vehicle@2.0-manager-lib
android.hardware.automotive.vehicle@2.0-default-impl-lib
android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib
android.hardware.automotive.vehicle@2.0-server-common-lib
android.hardware.automotive.vehicle@2.0-server-impl-lib
android.hardware.automotive.vehicle@2.0-manager-unit-tests
android.hardware.automotive.vehicle@2.0-default-impl-unit-tests
android.hardware.automotive.vehicle@2.0-service
android.hardware.automotive.vehicle@2.0-libproto-native

VehicleService

Android Automtive在硬件抽象层的主要服务。代码路径:hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp

启动

通过init.rc启动,init.rc配置在android.bp文件中

代码路径:hardware/interfaces/automotive/vehicle/2.0/default/Android.bp

cc_binary 
    name: "android.hardware.automotive.vehicle@2.0-service",
    defaults: ["vhal_v2_0_target_defaults"],
    vintf_fragments: [
        "android.hardware.automotive.vehicle@2.0-service.xml",
    ],
    init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
    vendor: true,
    relative_install_path: "hw",
    srcs: ["VehicleService.cpp"],
    shared_libs: [
        "libbase",
        "libjsoncpp",
        "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",
        "libqemu_pipe",
    ],

init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"]指定启动的配置文件。

rc文件: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

VehicleService::main

VehicleService启动的主函数就是main方法。

int main(int /* argc */, char* /* argv */ []) 
    auto store = std::make_unique<VehiclePropertyStore>(); //初始化VehiclePropertyStore
    auto connector = impl::makeEmulatedPassthroughConnector(); //创建一个连接者 EmulatedPassthroughConnector
    auto userHal = connector->getEmulatedUserHal(); //获取getEmulatedUserHal
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal); //初始化EmulatedVehicleHal
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get()); //初始化VehicleEmulator
    auto service = std::make_unique<VehicleHalManager>(hal.get()); //初始化VehicleHalManager
    connector->setValuePool(hal->getValuePool()); //创建value池

    configureRpcThreadpool(4, false /* callerWillJoin */); //初始化rpc线程池

    status_t status = service->registerAsService();

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

    // Setup a binder thread pool to be a car watchdog client.
    ABinderProcess_setThreadPoolMaxThreadCount(1); //初始化Binder线程池
    ABinderProcess_startThreadPool();
    sp<Looper> looper(Looper::prepare(0 /* opts */)); //初始化looper
    std::shared_ptr<WatchdogClient> watchdogClient =
            ndk::SharedRefBase::make<WatchdogClient>(looper, service.get()); //初始化watchdog
    // The current health check is done in the main thread, so it falls short of capturing the real
    // situation. Checking through HAL binder thread should be considered.
    if (!watchdogClient->initialize()) 
        ALOGE("Failed to initialize car watchdog client");
        return 1;
    
    ALOGI("Ready");
    while (true) 
        looper->pollAll(-1 /* timeoutMillis */); //启动looper
    

    return 1;

  1. 初始化VehiclePropertyStore,得到store指针
  2. 创建一个连接者 EmulatedPassthroughConnector
  3. 获取getEmulatedUserHal
  4. 初始化EmulatedVehicleHal,得到hal指针,初始化时,将VehiclePropertyStore指针作为参数传输了EmulatedVehicleHal构造方法中
  5. 初始化VehicleEmulator,得到emulator指针,初始化时,将EmulatedVehicleHal指针作为参数传入VehicleEmulator的构造方法中。
  6. 初始化VehicleHalManager,获得service智能指针。VehicleHalManager继承自IVehicle hidl接口,该接口在编译的时候自动生成了registerAsService方法,该方法就是将服务本身通过binder注册到hwservicemanager里面供其他进程连接。
  7. 创建value
  8. 初始化RPC线程池
  9. 初始化Binder线程池
  10. 初始化looper
  11. 初始化watchdog
  12. 启动looper

VehiclePropertyStore

用于记录和存储车辆属性。相当一个数据容器,保存了所有车辆属性的配置以及值的记录。

代码路径:

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

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

#ifndef android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
#define android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_

#include <cstdint>
#include <unordered_map>
#include <memory>
#include <mutex>

#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>

namespace android 
namespace hardware 
namespace automotive 
namespace vehicle 
namespace V2_0 

/**
 * Encapsulates work related to storing and accessing configuration, storing and modifying
 * vehicle property values.
 *
 * VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
 * to get value for all areas for particular property.
 *
 * This class is thread-safe, however it uses blocking synchronization across all methods.
 */
class VehiclePropertyStore 
public:
    /* Function that used to calculate unique token for given VehiclePropValue */
    using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;

private:
    struct RecordConfig  //一条记录
        VehiclePropConfig propConfig; //propConfig
        TokenFunction tokenFunction; //propValue
    ;

    struct RecordId 
        int32_t prop; //prop
        int32_t area; //area
        int64_t token; //token

        bool operator==(const RecordId& other) const; // ==重载操作符
        bool operator<(const RecordId& other) const; // <重载操作符
    ;

    using PropertyMap = std::map<RecordId, VehiclePropValue>; //recordId和vehiclePropValue的map
    using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>; //将两个数据合成一个返回

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); //移除一个值用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; //VehiclePropConfig
    const VehiclePropConfig* getConfigOrDie(int32_t propId) const; //VehiclePropConfig

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

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.
;

  // namespace V2_0
  // namespace vehicle
  // namespace automotive
  // namespace hardware
  // namespace android

#endif //android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
类型名称
数据结构RecordConfig
数据结构RecordId
方法registerProperty
方法writeValue
方法removeValue
方法removeValuesForProperty
方法readAllValues
方法readValuesForProperty
方法readValueOrNull
方法readValueOrNull
方法getAllConfigs
方法getConfigOrNull
方法getConfigOrDie
属性mLock
属性mConfigs
属性mPropertyValues
方法getRecordIdLocked
方法getValueOrNullLocked
方法findRangeLocked

VehiclePropertyStore::RecordConfig

属性记录配置

struct RecordConfig  //一条记录
    VehiclePropConfig propConfig; //propConfig
    TokenFunction tokenFunction; //propValue
;

VehiclePropertyStore::RecordId

属性记录

struct RecordId 
    int32_t prop; //prop
    int32_t area; //area
    int64_t token; //token

    bool operator==(const RecordId& other) const; // ==重载操作符
    bool operator<(const RecordId& other) const; // <重载操作符
;

VehiclePropertyStore::mPropertyValues

定义了一个PropertyMap的map表来保存属性值。

using PropertyMap = std::map<RecordId, VehiclePropValue>;
PropertyMap mPropertyValues;  // Sorted map of RecordId : VehiclePropValue.

VehiclePropertyStore::mConfigs

定义了一个无序map来保存属性配置

std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;

VehiclePropertyStore::mLock

一个锁

VehiclePropertyStore::registerProperty

注册一个车辆属性

void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
                                            VehiclePropertyStore::TokenFunction tokenFunc) 
    MuxGuard g(mLock);
    ALOGW("%s: mConfigs : 0x%x", __func__, config.prop);
    //很简单,mConfigs键值对插入key为config.prop, 值为RecordConfig, RecordConfig是个结构体,成员就是VehiclePropConfig跟一个函数指针。
    mConfigs.insert( config.prop, RecordConfig  config, tokenFunc  ); //注册property

VehiclePropertyStore::writeValue

写入属性值

bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
                                        bool updateStatus) 
    MuxGuard g(mLock);
    //首先从键值对的key集合里面查看是否当前需要写入属性值的属性id是否已经注册,如果当前属性id没有注册,则返回false,写入失败。
    if (!mConfigs.count(propValue.prop)) return false; //不包含属性返回

    RecordId recId = getRecordIdLocked(propValue); //获取RecordId
    //根据RecordId从map中获取Value值
    VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
    //如果当前没有保存该属性,则加入一条新的记录,否则的话,更新对应的值
    if (valueToUpdate == nullptr) 
        mPropertyValues.insert( recId, propValue );
        //插入更新的值
        ALOGW("%s: mPropertyValues : 0x%x", __func__, recId.prop);
        return true;
    

    // propValue is outdated and drops it.
    if (valueToUpdate->timestamp > propValue.timestamp) 
        //对比时间戳
        return false;
    
    // update the propertyValue.
    // The timestamp in propertyStore should only be updated by the server side. It indicates
    // the time when the event is generated by the server.
    //更新时间戳
    valueToUpdate->timestamp = propValue.timestamp;
    //更新值
    valueToUpdate->value = propValue.value;
    if (updateStatus) 
        ALOGW("%s: valueToUpdate : 0x%x", __func__, recId.prop);
        //更新状态
        valueToUpdate->status = propValue.status;
    
    return true;

VehiclePropertyStore::removeValue

移除一个VehiclePropValue

VehiclePropertyStore::removeValuesForProperty

根据propertyId移除一个VehiclePropValue

VehiclePropertyStore::readAllValues

读取全部的VehiclePropValue

VehiclePropertyStore::readValuesForProperty

根据propertyId读取VehiclePropValue

VehiclePropertyStore::readValueOrNull

读取一个VehiclePropValue

VehiclePropertyStore::getAllConfigs

获取全部的RecordConfig

VehiclePropertyStore::getConfigOrNull

获取一个RecordConfig

VehiclePropertyStore::getConfigOrDie

获取一个RecordConfig

DefaultConfig

定义车辆属性的配置,避免冲枚举到整型int的转换。

所有的配置都存储在kVehicleProperties数组中。

代码路径:automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h

const ConfigDeclaration kVehicleProperties[]
        .config =
                 
                         .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
                         .access = VehiclePropertyAccess::READ,
                         .changeMode = VehiclePropertyChangeMode::STATIC,
                 ,
         .initialValue = .floatValues = 15000.0f,

EmulatedVehicleConnector

一个虚拟的VehicleService的连接器,里面实现了VehicleHalClientVehicleHalServer

#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_

#include <vhal_v2_0/VehicleConnector.h>

#include "VehicleHalClient.h"
#include "VehicleHalServer.h"

namespace android 
namespace hardware 
namespace automotive 
namespace vehicle 
namespace V2_0 

namespace impl 

using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;

PassthroughConnectorPtr makeEmulatedPassthroughConnector();

  // namespace impl

  // namespace V2_0
  // namespace vehicle
  // namespace automotive
  // namespace hardware
  // namespace android

#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_

VehicleConnector

VehicleConnector这里的继承关系有点复杂

//EmulatedVehicleConnector.cpp
	class EmulatedPassthroughConnector : public PassthroughConnector
//EmulatedVehicleConnector.h
	using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
//VehicleConnector.h
	template <typename VehicleClientType, typename VehicleServerType>
	class IPassThroughConnector : public VehicleClientType, public VehicleServerType 

也就是说**EmulatedVehicleConnector继承了VehicleHalClientVehicleHalServer**

这里对一些方法做了实现

StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) override 
    return this->onSetProperty(value, updateStatus);


void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) override 
    return this->onPropertyValue(value, updateStatus);

当调用setProperty时会执行到VehicleHalServeronSetProperty方法。

当调用onPropertyValueFromCar时会执行到VehicleHalClientonPropertyValue方法。

VehicleHalServer

这包含本机和虚拟化 VHAL 服务器将使用的常见服务器操作。请注意,在虚拟化方案中,服务器可能在与 Android 不同的操作系统上运行。

代码路径:

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

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

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

继承关系:VehicleServer <-- VehicleHalServer <-- VehicleHalServer

类型名称
方法onGetAllPropertyConfig
方法onSetProperty
方法onPropertyValueFromCar
方法onDump
方法setValuePool
方法getEmulatedUserHal
方法getGenerator
方法getValuePool
方法onFakeValueGenerated
方法handleGenerateFakeDataRequest
方法createApPowerStateReq
方法createHwInputKeyProp
属性mEmulatedUserHal
属性mGeneratorHub
属性mValuePool
#pragma once

#include <vhal_v2_0/VehicleObjectPool.h>
#include <vhal_v2_0/VehicleServer.h>

#include "EmulatedUserHal.h"
#include "GeneratorHub.h"

namespace android::hardware::automotive::vehicle::V2_0::impl 

// This contains the common server operations that will be used by
// both native and virtualized VHAL server. Notice that in the virtualized
// scenario, the server may be run on a different OS than Android.
class VehicleHalServer : public IVehicleServer 
  public:
    // Methods from IVehicleServer

    std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;

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

    // Set the Property Value Pool used in this server
    void setValuePool(VehiclePropValuePool* valuePool);

    EmulatedUserHal* getEmulatedUserHal();

  private:
    using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;

    GeneratorHub* getGenerator();

    VehiclePropValuePool* getValuePool() const;

    void onFakeValueGenerated(const VehiclePropValue& value);

    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);

    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);

    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                             int32_t targetDisplay);

    // data members

  protected:
    EmulatedUserHal mEmulatedUserHal;

  private:
    GeneratorHub mGeneratorHub
            std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1);

    VehiclePropValuePool* mValuePoolnullptr;
;

  // namespace android::hardware::automotive::vehicle::V2_0::impl
  • VehicleHalServer::onSetProperty
StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) 
     
    //......

    // Some properties need to be treated non-trivially

    // In the real vhal, the value will be sent to Car ECU.
    // We just pretend it is done here and send back to HAL
    auto updatedPropValue = getValuePool()->obtain(value);
    updatedPropValue->timestamp = elapsedRealtimeNano();

    onPropertyValueFromCar(*updatedPropValue, updateStatus);
    return StatusCode::OK;

这里onPropertyValueFromCar会将变化通知回VehicleHalClient

void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) override 
    return this->onPropertyValue(value, updateStatus);

VehicleHalClient

本机和虚拟化 VHAL 客户端可能使用的常见客户端操作。

代码路径:

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

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

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

继承关系:VehicleClient <-- VehicleHalClient <-- VehicleHalClient

类型名称
方法VehicleHalClient
方法setProperty
方法onPropertyValue
方法dump
方法onPropertyValue
方法registerPropertyValueCallback
属性PropertyCallBackType
#pragma once

#include <vhal_v2_0/VehicleClient.h>

namespace android::hardware::automotive::vehicle::V2_0::impl 

// The common client operations that may be used by both native and
// virtualized VHAL clients.
class VehicleHalClient : public IVehicleClient 
  public:
    // Type of callback function for handling the new property values
    using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;

    // Method from IVehicleClient
    void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;

    void registerPropertyValueCallback(PropertyCallBackType&& callback);

  private:
    PropertyCallBackType mPropCallback;
;

  // namespace android::hardware::automotive::vehicle::V2_0::impl

EmulatedUserHal

用于通过lshal 调试请求模拟用户 HAL 行为的类。

EmulatedVehicleHal

实现了连接到仿真器而不是实车网络的车载HAL ,仿真器的实现逻辑与实际的逻辑相同。

代码路径 hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp

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

#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_

#include <map>
#include <memory>
#include <sys/socket.h>
#include <thread>
#include <unordered_set>

#include <utils/SystemClock.h>

#include <vhal_v2_0/RecurrentTimer.h>
#include <vhal_v2_0/VehicleHal.h>
#include "vhal_v2_0/VehiclePropertyStore.h"

#include "DefaultConfig.h"
#include "EmulatedUserHal.h"
#include "EmulatedVehicleConnector.h"
#include "GeneratorHub.h"
#include "VehicleEmulator.h"

namespace android 
namespace hardware 
namespace automotive 
namespace vehicle 
namespace V2_0 

namespace impl 

/** 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);
    ~EmulatedVehicleHal() = default;

    //  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:
    constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const 
        return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
    

    StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
    void onPropertyValue(const VehiclePropValue& value, bool updateStatus);

    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;
    VehicleHalClient* mVehicleClient;
    bool mInEmulator;
    bool mInitVhalValueOverride;
    std::vector<VehiclePropValue> mVehiclePropertiesOverride;
    EmulatedUserHal* mEmulatedUserHal;
;

  // impl

  // namespace V2_0
  // namespace vehicle
  // namespace automotive
  // namespace hardware
  // namespace android


#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_

属性接口

类型名称
方法onCreate
方法listProperties
方法get
方法set
方法subscribe
方法unsubscribe
方法dump
方法setPropertyFromVehicle
方法getAllProperties
方法getAllPropertiesOverride
方法handleGenerateFakeDataRequest
方法onPropertyValue
方法onContinuousPropertyTimer
方法isContinuousProperty
方法initStaticConfig
方法initObd2LiveFrame
方法initObd2FreezeFrame
方法fillObd2FreezeFrame
方法fillObd2DtcInfo
方法clearObd2FreezeFrames
属性mPropStore
属性mHvacPowerProps
属性mRecurrentTimer
属性mVehicleClient
属性mInEmulator
属性mInitVhalValueOverride
属性mVehiclePropertiesOverride
属性mEmulatedUserHal

EmulatedVehicleHal::EmulatedVehicleHal

EmulatedVehicleHal继承EmulatedVehicleHalIface,而EmulatedVehicleHalIface继承VehicleHalVehicleHal定义了和IVehicle中同样的接口,也就是说EmulatedVehicleHalIVehcle中的接口做了实现。

EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
                                       EmulatedUserHal* emulatedUserHal)
    : mPropStore(propStore),
      mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
      //mRecurrentTimer是一个工具类,内部维护一个线程,用来处理指定时间触发的事件,这个跟上层的Handler比较类似。
      mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
                                std::placeholders::_1)),
      mVehicleClient(client),
      mEmulatedUserHal(emulatedUserHal) 
    //注册DefaultConfig.h中定义的属性值
    initStaticConfig();
    for (size_t i = 0; i < arraysize(kVehicleProperties); i++) 
        mPropStore->registerProperty(kVehicleProperties[i].config);
    
    mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
                                                            this, std::placeholders::_1,
                                                            std::placeholders::_2));

    mInitVhalValueOverride =
            android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
    if (mInitVhalValueOverride) 
        getAllPropertiesOverride();
    

  1. auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);前面在VehicleService中创建EmulatedVehicleHal时,传入了前面创建的三个变量。

  2. mPropStore(propStore) 存储车辆属性变化的一个容器。

  3. mVehicleClient(client) 回调通知用的

  4. mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this一个处理持续变化Continuous车辆属性的计时器。

  5. initStaticConfig() 初始化车辆属性的配置

    void EmulatedVehicleHal::initStaticConfig() 
        for (auto&& it = std::begin(kVehicleProperties); it != std::end(kVehicleProperties); ++it) 
            const auto& cfg = it->config;
            VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
    
            switch (cfg.prop) 
                case OBD2_FREEZE_FRAME: 
                    tokenFunction = [](const VehiclePropValue& propValue) 
                        return propValue.timestamp;
                    ;
                    break;
                
                default:
                    break;
            
    
            mPropStore->registerProperty(cfg, tokenFunction);
        
    
    

    kVehicleProperties定义在DefaultConfig.h中,保存所有支持的车辆属性配置。

    mPropStore->registerProperty(cfg, tokenFunction)将所有的初始化配置存入mPropStore容器。

  6. mPropStore->registerProperty(kVehicleProperties[i].config)initStaticConfig好像重复了。

  7. mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,callback函数注册给mVehicleClient。回调时会触发onPropertyValue

  8. getAllPropertiesOverride更新一些需要重写的车辆属性配置。

EmulatedVehicleHal::get

获取一个车辆属性值

VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) 
    //当前我们要拿的属性值的属性ID是多少
    auto propId = requestedPropValue.prop;
    ALOGV("get(%d)", propId);
    //这个pool是一个用于存储VehiclePropValue的对象池,这个跟Message的实现好像。
    auto& pool = *getValuePool();
    VehiclePropValuePtr v = nullptr;
    //这个就是根据propId来获取值了,OBD2_FREEZE_FRAME是OBD检测到故障信息,
    //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:
            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;
            

            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
            if (internalPropValue != nullptr) 
                v = getValuePool()->obtain(*internalPropValue);
            

            *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
            break;
    
    if (v.get()) 
        v->timestamp = elapsedRealtimeNano();
    
    return v;

  1. auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue)这里从mPropStrore中取一个车辆属性,也就是从维护的数据容器中获取对应车辆属性的值。
  2. v->timestamp = elapsedRealtimeNano();更新获取当前车辆属性的时间戳。

EmulatedVehicleHal::set

设置一个车辆属性值,先将属性值写入到内存中保存,然后再通知车身更新该属性值,doSetValueFromClient这个函数就实现了相关的功能,这里暂且按下不表。这个set事件是来自客户端的调用,那车身信息如果发生变化时,如何set呢,答案是该模块还有一个名称setPropertyFromVehicle的函数,正是这个函数实现了车身数据变化之后,更新缓存的属性,并通知上层。

StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) 
    //这个常量定义为false,是因为这个set函数是给上层调用的,Android层
    //不能够改变属性值的状态,只有车身发送了该属性值过来了,才可改变属性状态,这个在下面会有体现。
    constexpr bool updateStatus = false;
    //这段代码用于测试的,生产一个假的数据请求事件。
    if (propValue.prop == kGenerateFakeDataControllingProperty) 
        // Send the generator controlling request to the server.
        // 'updateStatus' flag is only for the value sent by setProperty (propValue in this case)
        // instead of the generated values triggered by it. 'propValue' works as a control signal
        // here, since we never send the control signal back, the value of 'updateStatus' flag
        // does not matter here.
        auto status = mVehicleClient->setProperty(propValue, updateStatus);
        return status;
     else if (mHvacPowerProps.count(propValue.prop)) 
        //这里是判断当前属性值是否属于空调电源开关,如果是的情况下,去拿它值,如果当前开关没开,则返回当前状态不可用,设置失败的CODE
        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) 
            return StatusCode::NOT_AVAILABLE;
        
     else 
        // Handle property specific code
        switch (propValue.prop) 
            case OBD2_FREEZE_FRAME_CLEAR:
                return clearObd2FreezeFrames(propValue);
            case VEHICLE_MAP_SERVICE:
                // Placeholder for future implementation of VMS property in the default hal. For
                // now, just returns OK; otherwise, hal clients crash with property not supported.
                return StatusCode::OK;
        
    
    //status默认值为AVAILABLE
    if (propValue.status != VehiclePropertyStatus::AVAILABLE) 
        // Android side cannot set property status - this value is the
        // purview of the HAL implementation to reflect the state of
        // its under

Android Automotive OS知识体系

Android Automotive OS知识体系

Android 知识体系
Automotive概览

1、简介

Android Automotive OS (AAOS) 是汽车制造商在汽车中打造的信息娱乐平台。驾驶人员可以直接将兼容的媒体应用下载到汽车中,无需使用手机,并使用专为车载显示屏设计的界面。
什么是 Android Automotive?

  Automotive 借助各种总线拓扑,很多汽车子系统都可以实现互连以及与车载信息娱乐 (IVI) 系统的连接。不同的制造商提供的确切总线类型和协议之间有很大差异(甚至同一品牌的不同车型之间也是如此),例如控制器局域网 (CAN) 总线、区域互连网路 (LIN) 总线、面向媒体的系统传输 (MOST) 总线以及汽车级以太网和 TCP/IP 网络(如 BroadR-Reach)。


  Android Automotive 的硬件抽象层 (HAL) 为 Android 框架提供了一致的接口(无需考虑物理传输层)。此车载 HAL 是开发 Android Automotive 实现的接口。


  系统集成商可以将特定于功能的平台 HAL 接口(如 HVAC)与特定于技术的网络接口(如 CAN 总线)连接,以实现车载 HAL 模块。典型的实现可能包括运行专有实时操作系统 (RTOS) 的专用微控制器单元 (MCU),该微控制器单元用于 CAN 总线访问或类似操作,可通过串行链路连接到运行 Android Automotive 的 CPU。除了专用 MCU,还可以将总线访问作为虚拟 CPU 来实现。只要实现符合车载 HAL 的接口要求,每个合作伙伴都可以选择适合硬件的架构。

1.1 Android Automotive 和 Android

了解 Android Automotive 与整个 Android 生态系统之间的关系至关重要:

  • Android Automotive 就是 Android 平台。Android Automotive 并非 Android 的分支或并行开发版本。它与手机和平板电脑等设备上搭载的 Android 使用相同的代码库,位于同一个存储区中。它基于开发时间逾 10 载的强大平台和功能集构建而成,因此能够利用现有的安全模型、兼容性计划、开发者工具和基础架构,同时继续保持较高的可定制性和可移植性,完全免费提供并且开源。
  • Android Automotive 扩展了 Android 平台。在将 Android 打造为功能完善的信息娱乐平台的过程中,我们增加了对汽车特定要求、功能和技术的支持。Android Automotive 将是一个一站式全栈车载信息娱乐平台,就像现在的 Android 系统之于移动设备一样。

十多年来,运营商、原始设备制造商 (OEM) 和开发者一直在使用 Android 平台打造优质的设备、应用和体验。现在,Android Automotive 将 Android 的强大功能引入汽车之中,让汽车制造商得以打造满足数字时代需求的强大信息娱乐系统。

1.2 Android Automotive 和 Android Auto

两者的命名方式可能有点让人迷惑不解。下面介绍了它们之间的区别:

  • Android Auto 是一个基于用户的手机运行的平台,可通过 USB 连接将 Android Auto 用户体验投射到兼容的车载信息娱乐系统。Android Auto 支持专为车载用途而设计的应用。如需了解详情,请访问 developer.android.com/auto。
  • Android Automotive 是直接基于车载硬件运行的操作系统和平台。它是一个可定制程度非常高的全栈开源平台,可为信息娱乐体验提供强大的技术支持。Android Automotive 支持专为 Android 打造的应用,以及专为 Android Auto 打造的应用。

1.3 架构

车载 HAL 是汽车与车辆网络服务之间的接口定义:

  • Car API: 内有包含 CarSensorManager 在内的 API。如需详细了解受支持的 API,请参阅 /platform/packages/services/Car/car-lib
  • CarService: 位于 /platform/packages/services/Car/
  • 车载 HAL: 用于定义 OEM 可以实现的车辆属性的接口。包含属性元数据(例如,车辆属性是否为 int 以及允许使用哪些更改模式)。位于 hardware/libhardware/include/hardware/vehicle.h。如需了解基本参考实现,请参阅 hardware/libhardware/modules/vehicle/

2、车载信息娱乐 (IVI) 系统

其他请查看 Android 知识体系,关于基于Android的车载娱乐系统单独在里记录 Android Automotive OS知识体系

2.1 VehicleService

编号文档说明
1【IVI】VehicleService启动VehocleHal相关服务
2【IVI】车载设备硬件抽象层VHAL车载属性介绍,set\\get 简要流程

2.2 CarServiceHelperService

编号文档说明
1【IVI】CarServiceHelperService启动CarServiceHelperService车载服务启动入口

2.3 CarService

编号文档说明
1【IVI】CarService启动CarService车载相关服务创建并初始化,实质处理类ICarImpl
2【IVI】Car.java获取Car相关服务和对应管理器获取Car相关服务

3、虚拟机AVD

【IVI】Automotive虚拟机没有System image

以上是关于Android Automotive VehicleService的主要内容,如果未能解决你的问题,请参考以下文章

Android Automotive OS知识体系

Android Automotive OS知识体系

Android Automotive OS知识体系

Android 车机初体验:Auto,Automotive 傻傻分不清楚?

车机系统开发——Android Automotive

Android Automotive OS | Instrument Cluster