当前位置: 首页 > article >正文

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-serviceclass haluser vehicle_networkgroup system inet

VehicleService::main

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

int main(int /* argc */, char* /* argv */ []) {auto store = std::make_unique<VehiclePropertyStore>(); //初始化VehiclePropertyStoreauto connector = impl::makeEmulatedPassthroughConnector(); //创建一个连接者 EmulatedPassthroughConnectorauto userHal = connector->getEmulatedUserHal(); //获取getEmulatedUserHalauto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal); //初始化EmulatedVehicleHalauto emulator = std::make_unique<impl::VehicleEmulator>(hal.get()); //初始化VehicleEmulatorauto service = std::make_unique<VehicleHalManager>(hal.get()); //初始化VehicleHalManagerconnector->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 */)); //初始化looperstd::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; //propConfigTokenFunction tokenFunction; //propValue};struct RecordId {int32_t prop; //propint32_t area; //areaint64_t token; //tokenbool operator==(const RecordId& other) const; // ==重载操作符bool operator<(const RecordId& other) const; // <重载操作符};using PropertyMap = std::map<RecordId, VehiclePropValue>; //recordId和vehiclePropValue的mapusing 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); //移除一个值用propIdstd::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; //VehiclePropConfigconst VehiclePropConfig* getConfigOrDie(int32_t propId) const; //VehiclePropConfigprivate:RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const; //获取RecordIdconst VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const; //获取VehiclePropValuePropertyMapRange findRangeLocked(int32_t propId) const; //获取PropertyMapRangeprivate: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; //propConfigTokenFunction tokenFunction; //propValue
};

VehiclePropertyStore::RecordId

属性记录

struct RecordId {int32_t prop; //propint32_t area; //areaint64_t token; //tokenbool 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.cppclass EmulatedPassthroughConnector : public PassthroughConnector
//EmulatedVehicleConnector.husing PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
//VehicleConnector.htemplate <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 IVehicleServerstd::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;// Set the Property Value Pool used in this servervoid 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 membersprotected:EmulatedUserHal mEmulatedUserHal;private:GeneratorHub mGeneratorHub{std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};VehiclePropValuePool* mValuePool{nullptr};
};}  // 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 HALauto 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 valuesusing PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;// Method from IVehicleClientvoid 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 VehicleHalvoid 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 EmulatedVehicleHalIfacebool 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)) {//这里是判断当前属性值是否属于空调电源开关,如果是的情况下,去拿它值,如果当前开关没开,则返回当前状态不可用,设置失败的CODEauto 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 codeswitch (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默认值为AVAILABLEif (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 underlying hardwarereturn StatusCode::INVALID_ARG;}//读取该属性值id的当前存储的Propauto currentPropValue = mPropStore->readValueOrNull(propValue);if (currentPropValue == nullptr) {return StatusCode::INVALID_ARG;}//如果目前属性值状态不可用,则上层不能设置,返回失败if (currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {// do not allow Android side to set() a disabled/error propertyreturn StatusCode::NOT_AVAILABLE;}if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {// Emulator does not support remote brightness control, b/139959479// do not send it down so that it does not bring unnecessary property change event// return other error code, such NOT_AVAILABLE, causes Emulator to be freezing// TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixedreturn StatusCode::OK;}/*** After checking all conditions, such as the property is available, a real vhal will* sent the events to Car ECU to take actions.*/// Send the value to the vehicle server, the server will talk to the (real or emulated) car//通知汽车,设置属性值,这里是告诉模拟器,该值需要重新设置,调用的这个函数等下再说。auto setValueStatus = mVehicleClient->setProperty(propValue, updateStatus);if (setValueStatus != StatusCode::OK) {return setValueStatus;}return StatusCode::OK;
}
  1. auto currentPropValue = mPropStore->readValueOrNull(propValue);从数据容器中读取一下当前的车辆属性值。

  2. 在检查了所有条件(例如属性是否可用)后,真正的vhal会将事件发送到车辆的ECU以采取行动。

    /**
    * After checking all conditions, such as the property is available, a real vhal will
    * sent the events to Car ECU to take actions.
    */
    
  3. auto setValueStatus = mVehicleClient->setProperty(propValue, updateStatus)这里实际是将值发送到车辆服务,服务将与(真实或模拟的)发送给汽车。
    这里对车辆属性的设置实际交给VehicleHalClient处理
    VehicleHalClient实际是VehicleConnector对象,最后会调用VehicleServeronSetProperty方法。

EmulatedVehicleHal::subscribe

订阅车辆属性

StatusCode EmulatedVehicleHal::subscribe(int32_t property, float sampleRate) {ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);if (isContinuousProperty(property)) {// sampleRate是属性值更新的频率mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);}return StatusCode::OK;
}
  1. isContinuousProperty主要是判断该属性值的change类型是不是连续类型的,如果是连续类型Continuous的,就向RecurrentTimer中注册事件
    RecurrentTimer是一个工具类,可以把它理解为一个另类的Handler, 其内部运行着一个线程维护着一个循环,当向其注册一个事件时,内部根据事件频率算出触发事件的事件,然后定期触发回调方法,跟Handler唯一不同的是,Handler的sendMesssageAtTime发完就没了,这个RecurrentTimer是如果你注册了事件,如果不取消注册,则事件会一直定期触发。

EmulatedVehicleHal::unsubscribe

取消订阅一个车辆属性

StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {ALOGI("%s propId: 0x%x", __func__, property);if (isContinuousProperty(property)) {mRecurrentTimer.unregisterRecurrentEvent(property);}return StatusCode::OK;
}

EmulatedVehicleHal::onContinuousPropertyTimer

订阅了一个车辆,当达到时间后会触发onContinuousPropertyTimer,这个函数指针在EmulatedVehicleHal初始化的时候,就作为参数传给RecurrentTimer,然后在这个函数中调用 doHalEvent(std::move(v)); 触发回调事件,将属性值上报。

void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {VehiclePropValuePtr v;auto& pool = *getValuePool();for (int32_t property : properties) {if (isContinuousProperty(property)) {auto internalPropValue = mPropStore->readValueOrNull(property);if (internalPropValue != nullptr) {v = pool.obtain(*internalPropValue);}} else {ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);}if (v.get()) {v->timestamp = elapsedRealtimeNano();doHalEvent(std::move(v));}}
}

代码路径:automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h

void doHalEvent(VehiclePropValuePtr v) {mOnHalEvent(std::move(v));//vehiclehal.h
}

mOnHalEvent是一个函数指针,其对应函数定义在VehicleHalManager中,如下

void VehicleHalManager::onHalEvent(VehiclePropValuePtr v) {mEventQueue.push(std::move(v));
}

最终由BatchingConsumer取出该事件,回调给上层;mOnHalEvent函数指针在VehicleHalManager初始化的时候,会将其作为参数传给EmulatedVehicleHal

mHal->init(&mValueObjectPool,std::bind(&VehicleHalManager::onHalEvent, this, _1),std::bind(&VehicleHalManager::onHalPropertySetError, this,_1, _2, _3));

EmulatedVehicleHal::onPropertyValue

当车辆属性值发生变化时,会执行此方法进行通知。

void EmulatedVehicleHal::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);if (mPropStore->writeValue(*updatedPropValue, updateStatus)) {getEmulatorOrDie()->doSetValueFromClient(*updatedPropValue);doHalEvent(std::move(updatedPropValue));}
}

doHalEvent(std::move(updatedPropValue));同上,最后也会由VehicleHalManager回调上层。

该方法的注册在EmulatedVehicleHal的构造函数中。

mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,this, std::placeholders::_1,std::placeholders::_2));

当被调用VehicleHalClientonPropertyValue函数时,则会执行EmulatedVehicleHalonPropertyValue


VehicleHalManager

VehicleHalManager 是实现了IVehicle接口的类,处理HIDL接口调用的逻辑。

VehicleHalManager继承自IVehicle hidl接口,该接口在编译的时候自动生成了registerAsService方法,该方法就是将服务本身通过binder注册到hwservicemanager里面供其他进程连接。VehicleHalManager实际就是HIDL中IVehicle的服务端,它实现了IVehicle定义的接口。

  • getAllPropConfigs
    获取所有的车辆属性配置
  • getPropConfigs
    获取对应车辆属性的配置
  • set
    设置车辆属性值
  • get
    获取车辆属性值
#ifndef android_hardware_automotive_vehicle_V2_0_VehicleHalManager_H_
#define android_hardware_automotive_vehicle_V2_0_VehicleHalManager_H_#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>#include <list>
#include <map>
#include <memory>
#include <set>#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>#include "ConcurrentQueue.h"
#include "SubscriptionManager.h"
#include "VehicleHal.h"
#include "VehicleObjectPool.h"
#include "VehiclePropConfigIndex.h"namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
namespace V2_0 {/*** 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.*/
class VehicleHalManager : public IVehicle {
public:VehicleHalManager(VehicleHal* vehicleHal): mHal(vehicleHal),mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,this, std::placeholders::_1)) {init();}virtual ~VehicleHalManager();void init();// ---------------------------------------------------------------------------------------------// Methods derived from IVehicleReturn<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;Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;private:using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;// Returns true if needs to call again shortly.using RetriableAction = std::function<bool()>;// ---------------------------------------------------------------------------------------------// Events received from VehicleHalvoid onHalEvent(VehiclePropValuePtr  v);void onHalPropertySetError(StatusCode errorCode, int32_t property,int32_t areaId);// ---------------------------------------------------------------------------------------------// This method will be called from BatchingConsumer threadvoid 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);// Dump and commands// TODO: most functions below (exception dump() and cmdSetOne()) should be const, but they rely// on IVehicle.get(), which isn't...void cmdDump(int fd, const hidl_vec<hidl_string>& options);void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);static bool checkCallerHasWritePermissions(int fd);static bool safelyParseInt(int fd, int index, std::string s, int* out);void cmdHelp(int fd) const;void cmdListAllProperties(int fd) const;void cmdDumpAllProperties(int fd);void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);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;std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;SubscriptionManager mSubscriptionManager;hidl_vec<VehiclePropValue> mHidlVecOfVehiclePropValuePool;ConcurrentQueue<VehiclePropValuePtr> mEventQueue;BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer;VehiclePropValuePool mValueObjectPool;
};}  // namespace V2_0
}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android

VehicleHalManager::get

获取一个车辆属性

Return<void> VehicleHalManager::get(const VehiclePropValue& requestedPropValue, get_cb _hidl_cb) {const auto* config = getPropConfigOrNull(requestedPropValue.prop);if (config == nullptr) {ALOGE("Failed to get value: config not found, property: 0x%x",requestedPropValue.prop);_hidl_cb(StatusCode::INVALID_ARG, kEmptyValue);return Void();}if (!checkReadPermission(*config)) {_hidl_cb(StatusCode::ACCESS_DENIED, kEmptyValue);return Void();}StatusCode status;auto value = mHal->get(requestedPropValue, &status);_hidl_cb(status, value.get() ? *value : kEmptyValue);return Void();
}
  1. const auto* config = getPropConfigOrNull(requestedPropValue.prop)获取车辆属性的配置

  2. checkReadPermission(*config)检查车辆属性的权限

    bool VehicleHalManager::checkReadPermission(const VehiclePropConfig &config) const {if (!(config.access & VehiclePropertyAccess::READ)) {ALOGW("Property 0%x has no read access", config.prop);return false;} else {return true;}
    }
    
  3. _hidl_cb(status, value.get() ? *value : kEmptyValue)返回获取结果。

VehicleHalManager::set

设置一个车辆属性

Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {auto prop = value.prop;const auto* config = getPropConfigOrNull(prop);if (config == nullptr) {ALOGE("Failed to set value: config not found, property: 0x%x", prop);return StatusCode::INVALID_ARG;}if (!checkWritePermission(*config)) {return StatusCode::ACCESS_DENIED;}handlePropertySetEvent(value);auto status = mHal->set(value);return Return<StatusCode>(status);
}
  1. const auto* config = getPropConfigOrNull(prop);先检查有没有这个车辆属性。
  2. checkWritePermission(*config)检查权限
  3. handlePropertySetEvent(value)通知订阅者此车辆属性被设置了。
  4. auto status = mHal->set(value)交给EmulatedVehicleHal设置车辆属性

VehicleHalManager::subscribe

订阅对车辆属性

Return<StatusCode> VehicleHalManager::subscribe(const sp<IVehicleCallback> &callback,const hidl_vec<SubscribeOptions> &options) {hidl_vec<SubscribeOptions> verifiedOptions(options);for (size_t i = 0; i < verifiedOptions.size(); i++) {SubscribeOptions& ops = verifiedOptions[i];auto prop = ops.propId;const auto* config = getPropConfigOrNull(prop);if (config == nullptr) {ALOGE("Failed to subscribe: config not found, property: 0x%x",prop);return StatusCode::INVALID_ARG;}if (ops.flags == SubscribeFlags::UNDEFINED) {ALOGE("Failed to subscribe: undefined flag in options provided");return StatusCode::INVALID_ARG;}if (!isSubscribable(*config, ops.flags)) {ALOGE("Failed to subscribe: property 0x%x is not subscribable",prop);return StatusCode::INVALID_ARG;}ops.sampleRate = checkSampleRate(*config, ops.sampleRate);}std::list<SubscribeOptions> updatedOptions;auto res = mSubscriptionManager.addOrUpdateSubscription(getClientId(callback),callback, verifiedOptions,&updatedOptions);if (StatusCode::OK != res) {ALOGW("%s failed to subscribe, error code: %d", __func__, res);return res;}for (auto opt : updatedOptions) {mHal->subscribe(opt.propId, opt.sampleRate);}return StatusCode::OK;
}
  1. const auto* config = getPropConfigOrNull(prop)获取车辆属性,判断是否有此配置
  2. isSubscribable(*config, ops.flags)判断是否已经订阅
  3. ops.sampleRate = checkSampleRate(*config, ops.sampleRate);检查订阅的频率
  4. auto res = mSubscriptionManager.addOrUpdateSubscription更新订阅的状态。
  5. mHal->subscribe(opt.propId, opt.sampleRate)通知EmulatedVehicleHal更新订阅信息。

VehicleHalManager::unsubscribe

取消订阅车辆属性

VehicleHalManager::init

初始化VehicleHalManager配置

void VehicleHalManager::init() {ALOGI("VehicleHalManager::init");mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);mBatchingConsumer.run(&mEventQueue,kHalEventBatchingTimeWindow,std::bind(&VehicleHalManager::onBatchHalEvent,this, _1));mHal->init(&mValueObjectPool,std::bind(&VehicleHalManager::onHalEvent, this, _1),std::bind(&VehicleHalManager::onHalPropertySetError, this,_1, _2, _3));// Initialize index with vehicle configurations received from VehicleHal.auto supportedPropConfigs = mHal->listProperties();mConfigIndex.reset(new VehiclePropConfigIndex(supportedPropConfigs));std::vector<int32_t> supportedProperties(supportedPropConfigs.size());for (const auto& config : supportedPropConfigs) {supportedProperties.push_back(config.prop);}
}
  1. mBatchingConsumer.run(&mEventQueu运行处理回调的处理者
  2. mHal->init(&mValueObjectPool设置回调的响应函数onHalEventonHalPropertySetError

VehicleHalManager::onHalEvent

将事件添加到消息队列

void VehicleHalManager::onHalEvent(VehiclePropValuePtr v) {mEventQueue.push(std::move(v));
}

VehicleHalManager::onHalPropertySetError

通知订阅者设置失败的情况。

void VehicleHalManager::onHalPropertySetError(StatusCode errorCode,int32_t property,int32_t areaId) {const auto& clients =mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::EVENTS_FROM_CAR);for (const auto& client : clients) {client->getCallback()->onPropertySetError(errorCode, property, areaId);}
}

VehicleHalManager::onBatchHalEvent

回调给应用的车辆属性变化

void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>& values) {const auto& clientValues =mSubscriptionManager.distributeValuesToClients(values, SubscribeFlags::EVENTS_FROM_CAR);for (const HalClientValues& cv : clientValues) {auto vecSize = cv.values.size();hidl_vec<VehiclePropValue> vec;if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);} else {vec.resize(vecSize);}int i = 0;for (VehiclePropValue* pValue : cv.values) {shallowCopy(&(vec)[i++], *pValue);}auto status = cv.client->getCallback()->onPropertyEvent(vec);if (!status.isOk()) {ALOGE("Failed to notify client %s, err: %s",toString(cv.client->getCallback()).c_str(),status.description().c_str());}}
}
  1. auto status = cv.client->getCallback()->onPropertyEvent(vec)回调给订阅者车辆属性变化

VehicleEmulator

车辆模拟器使用的车辆HAL的扩展,可以基于此接口进行socket通信来实现依稀VHAL的功能。

运用Pipe管道或者socket通讯的方式,跟模拟器之间收发通过protobuf封装的数据,模块内部实现了protobuf数据的解析与封装,用来触发设置,获取属性值的事件等。

VehicleEmulator::processMessage

处理一条接收的消息,消息可以分为五类

  • GET_CONFIG_CMD
  • GET_CONFIG_ALL_CMD
  • GET_PROPERTY_CMD
  • GET_PROPERTY_ALL_CMD
  • SET_PROPERTY_CMD
void VehicleEmulator::processMessage(vhal_proto::EmulatorMessage const& rxMsg,vhal_proto::EmulatorMessage& respMsg) {switch (rxMsg.msg_type()) {case vhal_proto::GET_CONFIG_CMD:doGetConfig(rxMsg, respMsg);break;case vhal_proto::GET_CONFIG_ALL_CMD:doGetConfigAll(rxMsg, respMsg);break;case vhal_proto::GET_PROPERTY_CMD:doGetProperty(rxMsg, respMsg);break;case vhal_proto::GET_PROPERTY_ALL_CMD:doGetPropertyAll(rxMsg, respMsg);break;case vhal_proto::SET_PROPERTY_CMD:doSetProperty(rxMsg, respMsg);break;default:ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());respMsg.set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);break;}
}

VehicleHalProto

通信数据使用proto封装。数据定义在hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto

syntax = "proto2";package vhal_proto;// CMD messages are from workstation --> VHAL
// RESP messages are from VHAL --> workstation
enum MsgType {GET_CONFIG_CMD                      = 0;GET_CONFIG_RESP                     = 1;GET_CONFIG_ALL_CMD                  = 2;GET_CONFIG_ALL_RESP                 = 3;GET_PROPERTY_CMD                    = 4;GET_PROPERTY_RESP                   = 5;GET_PROPERTY_ALL_CMD                = 6;GET_PROPERTY_ALL_RESP               = 7;SET_PROPERTY_CMD                    = 8;SET_PROPERTY_RESP                   = 9;SET_PROPERTY_ASYNC                  = 10;
}
enum Status {RESULT_OK                           = 0;ERROR_UNKNOWN                       = 1;ERROR_UNIMPLEMENTED_CMD             = 2;ERROR_INVALID_PROPERTY              = 3;ERROR_INVALID_AREA_ID               = 4;ERROR_PROPERTY_UNINITIALIZED        = 5;ERROR_WRITE_ONLY_PROPERTY           = 6;ERROR_MEMORY_ALLOC_FAILED           = 7;ERROR_INVALID_OPERATION             = 8;
}enum VehiclePropStatus {AVAILABLE                           = 0;UNAVAILABLE                         = 1;ERROR                               = 2;
}message VehicleAreaConfig {required int32  area_id             = 1;optional sint32 min_int32_value     = 2;optional sint32 max_int32_value     = 3;optional sint64 min_int64_value     = 4;optional sint64 max_int64_value     = 5;optional float  min_float_value     = 6;optional float  max_float_value     = 7;
}message VehiclePropConfig {required int32             prop                = 1;optional int32             access              = 2;optional int32             change_mode         = 3;optional int32             value_type          = 4;optional int32             supported_areas     = 5;     // Deprecated - DO NOT USErepeated VehicleAreaConfig area_configs        = 6;optional int32             config_flags        = 7;repeated int32             config_array        = 8;optional string            config_string       = 9;optional float             min_sample_rate     = 10;optional float             max_sample_rate     = 11;
};message VehiclePropValue {// common datarequired int32  prop                = 1;optional int32  value_type          = 2;optional int64  timestamp           = 3;    // required for valid data from HAL, skipped for setoptional VehiclePropStatus  status  = 10;   // required for valid data from HAL, skipped for set// valuesoptional int32  area_id             = 4;repeated sint32 int32_values        = 5;    // this also covers boolean value.repeated sint64 int64_values        = 6;repeated float  float_values        = 7;optional string string_value        = 8;optional bytes  bytes_value         = 9;
};// This structure is used to notify what values to get from the Vehicle HAL
message VehiclePropGet {required int32 prop                 = 1;optional int32 area_id              = 2;
};message EmulatorMessage {required MsgType           msg_type = 1;optional Status            status   = 2;    // Only for RESP messagesrepeated VehiclePropGet    prop     = 3;    // Provided for getConfig, getProperty commandsrepeated VehiclePropConfig config   = 4;repeated VehiclePropValue  value    = 5;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/58377.html

如若内容造成侵权/违法违规/事实不符,请联系我爱学习网进行投诉反馈,一经查实,立即删除!

相关文章:

Android Automotive(七) VehicleService

Android Automotive&#xff08;七&#xff09; VehicleService VehicleService 是Android Automotive在硬件抽象层的一个核心native服务。处理和车辆相关功能&#xff0c;为系统提供获取车身信息以及设置相关状态的接口。 HAL接口 从Android O (8.0) 开始&#xff0c;Googl…...

贪心c++(结合LeetCode例题)

目录 前言 LeetCode455分发饼干 思考 算法思路 LeetCode376摆动序列 思考 思路 代码 前言 有1元&#xff0c;5元10&#xff0c;元&#xff0c;20元&#xff0c;100元&#xff0c;200&#xff0c;元的钞票无穷多张。先使用这些钞票支付x元支付x元&#xff0c;最少需要…...

【python】文本处理:删除包含关键词的行、删除指定列、删除指定字符、替换关键字……...

目录 1、行处理 删除文件中包含关键词的行 删除TXT中的带/不带指定字符的行(并保留带指定字符的行) 删除匹配or不匹配某些条件的行 2、字符处理 删除特定字符 1.1、删除特定位置的字符 1.2、删除指定字符 1.3、删除每一行首/尾匹配条件的字符 正则表达式 替换文件里的字符 3、列…...

手写节流防抖函数

1. 认识防抖和节流函数 防抖和节流的概念最早不是出现在软件工程中&#xff0c;防抖是出现在电子元件中&#xff0c;节流是出现的流体流动中。 而javascript是事件驱动的&#xff0c;大量的操作会触发事件&#xff0c;加入到事件队列中处理而对于某些频繁的事件处理会造成性能…...

camunda_11_connector

Camunda 的 service task 推荐使用 external task, 它有很多优点: 流程引擎可以做到轻量级, 流程引擎实例可以支持更多的业务.解耦流程引擎和业务代码, 以后的升级和部署将非常方便.借助external task SDK, 业务代码实现也非常简单external task 采用 pull 模式, 由 external t…...

通达信自动交易接口设置止损程序解析

通达信自动交易接口设置止损程序并不是很难&#xff0c;对于交易者来说&#xff0c;还是需要去学习一些编程知识&#xff0c;像交易中的止损程序&#xff0c;可以这样去编写和输入你的止损策略&#xff1a; &#xff08;1&#xff09;# 设置买卖止损值 def set_stop_lose_n…...

MySQL事务的理解

什么是事务 事务是是数据库操作的最小的单元&#xff0c;它包含了一个或者多个操作命令&#xff0c;这些命令作为一个整体来执 行&#xff0c;要么一起成功要么一起失败&#xff0c;事务是不可在分的一个整体的操作集合。 事务具备的四大特性 原子性&#xff1a;事务是一个…...

ubantu服务器崩溃,重装系统如何使用之前的账号

1.进入root账户下&#xff1a; sudo su 2.查看账号拥有者和所属组 ls -la 2.给现在系统&#xff0c;添加原来相同的已存在账号名&#xff1a; adduser newusername 注意&#xff1a;报告已存在用户名称&#xff01;不用管&#xff0c;这个错误。已经添加到新系统中了。 3.修…...

Python 逻辑回归

逻辑回归分类 训练二元分类器 加载仅有两个分类的数据 from sklearn.linear_model import LogisticRegression from sklearn import datasets from sklearn.preprocessing import StandardScaleriris datasets.load_iris() features iris.data[:100,:] target iris.target…...

web前端面试题附答案016-怎么让顶部轮播图渲染的更快?

一、为什么强调轮播图&#xff1f; 很多时候我们强调用户体验&#xff0c;而这里更多时候我们更强调完美的首屏体验&#xff0c;而现在几乎每个网站顶部第一个大模块就是轮播图。轮播图占得区域最大&#xff0c;图片质量也更高&#xff0c;几乎一张图片的面积&#xff0c;体积就…...

springboot-内置Tomcat的配置和切换

基本介绍1.SpringBoot支持的webServer:Tomcat&#xff0c;Jetty&#xff0c;or Undertow2.SpringBoot应用启动是Web应用时。web场景包-导入tomcat3.支持对Tomcat(也可以是Jetty、Undertow)的配置和切换配置Tomcat方法一&#xff1a;通过application.yml完成配置(推荐方式&#…...

NAND VT Distribution 和失效模式

Vt Distribution是NAND Flash非常重要的一个特性。 1 从NMOS Vt到FGNMOS Vt 阈值电压(Vt或Vth)的概念是从MOS(Metal-Oxide-Semicondutor)来的。MOS的工作原理就像一个水库,Gate就是闸,闸抬起来(VGate≥Vth)电流就可以流过沟道(Channel),闸放下去(VGate<Vth)电流就不可以流…...

【C语言】编程初学者入门训练(1)

文章目录1. 实践出真知2. 我是大V3. 有容乃大4. 小飞机5. 缩短2进制6. 十六进制转十进制7. printf的返回值8. 成绩输入输出9. 学生基本信息输入输出10. 字符圣诞树1. 实践出真知 题目内容&#xff1a;于老师经常告诉我们“学习编程最好的办法就是上机实践&#xff0c;因为你要对…...

Python numpy.interp实例讲

​​​本文章向大家介绍Python numpy.interp实例讲解&#xff0c;主要分析其语法、参数、返回值和注意事项&#xff0c;并结合实例形式分析了其使用技巧&#xff0c;希望通过本文能帮助到大家理解应用这部分内容。用法: numpy.interp(x, xp, fp, leftNone, rightNone, periodN…...

Xavier参数初始化方法和Kaiming参数初始化方法详细介绍及其原理详解

相关文章 梯度下降算法、随机梯度下降算法、动量随机梯度下降算法、AdaGrad算法、RMSProp算法、Adam算法详细介绍及其原理详解反向传播算法和计算图详细介绍及其原理详解激活函数、Sigmoid激活函数、tanh激活函数、ReLU激活函数、Leaky ReLU激活函数、Parametric ReLU激活函数…...

线程池EterfreeA/ThreadPool的使用

在GitHub上有个线程池项目&#xff0c;地址为 https://github.com/EterfreeA/ThreadPool &#xff0c;开源&#xff0c;它的License为AFL-3.0&#xff0c;这里了解学习下&#xff0c;code中有较多的中文说明: (1).Core.hpp: 一些define和size函数 (2).DoubleQueue.…...

Python科学计算:用NumPy快速处理数据

NumPy是Python 中一个非常重要的第三方库 它不仅是 Python 中使用最多的第三方库&#xff0c;而且还是 SciPy、Pandas 等数据科学的基础 库。它所提供的数据结构比 Python 自身的“更高级、更高效”&#xff0c;可以这么说&#xff0c;NumPy 所 提供的数据结构是 Python 数据…...

基于python实现的生成对抗网络GAN

项目简介 这篇文章主要介绍了生成对抗网络(Generative Adversarial Network),简称 GAN。 GAN 可以看作是一种可以生成特定分布数据的模型。 2.生成人脸图像 下面的代码是使用 Generator 来生成人脸图像,Generator 已经训练好保存在 pkl 文件中,只需要加载参数即可。由…...

Matlab----绘图以及文件储存

目录 二维曲线 基础函数&#xff1a;plot/fplot 绘制图形的辅助操作 文件存储 二维曲线 基础函数&#xff1a;plot/fplot &#xff08;1&#xff09;plot函数的基本用法&#xff1a;plot(x,y)其中x和y分别用于储存x坐标和y坐标数据 &#xff08;2&#xff09;最简单plot函…...

Docker - 12. 容器卷基本概念

目录 1. 容器卷是什么&#xff1f; 2. 容器卷的特点 1. 容器卷是什么&#xff1f; 卷就是目录或文件&#xff0c;存在于一个或者多个容器中&#xff0c;由docker挂载到容器&#xff0c;但不属于联合文件系统&#xff0c;因此能够绕过联合文件系统而提供一些用于存储或共享数…...