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
VehiclePropertyType | enum |
VehicleArea | enum |
VehiclePropertyGroup | enum |
VehicleProperty | enum |
VehicleVendorPermission | enum |
VehiclePropertyChangeMode | enum |
VehiclePropertyAccess | enum |
VehiclePropertyStatus | enum |
VehicleAreaSeat | enum |
VehicleAreaWindow | enum |
VehicleAreaDoor | enum |
VehicleAreaMirror | enum |
VehicleAreaWheel | enum |
VehicleAreaConfig | struct |
VehiclePropConfig | struct |
VehiclePropValue | struct |
编译模块
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;
- 初始化
VehiclePropertyStore
,得到store
指针 - 创建一个连接者
EmulatedPassthroughConnector
- 获取
getEmulatedUserHal
- 初始化
EmulatedVehicleHal
,得到hal
指针,初始化时,将VehiclePropertyStore
指针作为参数传输了EmulatedVehicleHal
构造方法中 - 初始化
VehicleEmulator
,得到emulator
指针,初始化时,将EmulatedVehicleHal
指针作为参数传入VehicleEmulator
的构造方法中。 - 初始化
VehicleHalManager
,获得service
智能指针。VehicleHalManager
继承自IVehicle hidl
接口,该接口在编译的时候自动生成了registerAsService
方法,该方法就是将服务本身通过binder
注册到hwservicemanager
里面供其他进程连接。 - 创建
value
池 - 初始化RPC线程池
- 初始化Binder线程池
- 初始化
looper
- 初始化
watchdog
- 启动
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
的连接器,里面实现了VehicleHalClient
和VehicleHalServer
#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
继承了VehicleHalClient
和VehicleHalServer
**
这里对一些方法做了实现
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
时会执行到VehicleHalServer
的onSetProperty
方法。
当调用onPropertyValueFromCar
时会执行到VehicleHalClient
的onPropertyValue
方法。
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
继承VehicleHal
。VehicleHal
定义了和IVehicle
中同样的接口,也就是说EmulatedVehicleHal
对IVehcle
中的接口做了实现。
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();
-
auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
前面在VehicleService
中创建EmulatedVehicleHal
时,传入了前面创建的三个变量。 -
mPropStore(propStore)
存储车辆属性变化的一个容器。 -
mVehicleClient(client)
回调通知用的 -
mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this
一个处理持续变化Continuous
车辆属性的计时器。 -
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
容器。 -
mPropStore->registerProperty(kVehicleProperties[i].config)
和initStaticConfig
好像重复了。 -
mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
将callback
函数注册给mVehicleClient
。回调时会触发onPropertyValue
-
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;
auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue)
这里从mPropStrore
中取一个车辆属性,也就是从维护的数据容器中获取对应车辆属性的值。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 underAndroid Automotive OS知识体系
Android Automotive OS知识体系
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的主要内容,如果未能解决你的问题,请参考以下文章