1 概述
VehicleHal是AOSP中车辆服务相关的hal层服务。它主要定义了与汽车硬件交互的标准化接口和属性管理,是一个独立的进程。
2 进程启动
VehicleHal相关代码在源码树中的hardware/interfaces/automotive
目录下
首先看下Android.bp文件:
cpp
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",
],
}
标准的hal服务层定义,入口在VehicleService.cpp,其他依赖文件在static_libs中定义。服务的可执行文件编译完成之后的名称是android.hardware.automotive.vehicle@2.0-service。
进程是hal服务进程,由init通过解析rc文件进行拉起
cpp
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
class hal
user vehicle_network
group system inet
进程名vendor.vehicle-hal-2.0,执行的就是/vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service这个可执行文件,class为hal,用户是vehicle_network,用户组是system和inet。
在init中class_start hal的时候启动该hal进程。
3 VHAL初始化
VHAL进程的入口在VehicleService.cpp中的main函数
hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp
cpp
// xy:VHAL的入口函数,由init进程启动
int main(int /* argc */, char* /* argv */ []) {
// xy:缓存属性值的地方
auto store = std::make_unique<VehiclePropertyStore>();
// xy:模拟与真实车辆的连接
auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
// xy:模拟Hal,Hal的具体实现
auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
// xy:汽车模拟类,模拟车辆信号
auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
// xy:VHAL的服务实现入口
auto service = std::make_unique<VehicleHalManager>(hal.get());
// xy:设置存储属性值的池子,便于重复使用
connector->setValuePool(hal->getValuePool());
// xy:设置binder线程数量
configureRpcThreadpool(4, false /* callerWillJoin */);
ALOGI("Registering as service...");
// xy:将当前服务注册到HwServiceManager中
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.
// xy:watchDog设置
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
sp<Looper> looper(Looper::prepare(0 /* opts */));
std::shared_ptr<WatchdogClient> watchdogClient =
ndk::SharedRefBase::make<WatchdogClient>(looper, service.get());
// 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 */);
}
return 1;
}
接下来逐步解析各个模块的初始化
3.1 VehiclePropertyStore初始化
VehiclePropertyStore类的主要职责是缓存车辆数据,采用默认构造函数,构造函数中没有初始化逻辑。
cpp
using PropertyMap = std::map<RecordId, VehiclePropValue>;
std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;
PropertyMap mPropertyValues; // Sorted map of RecordId : VehiclePropValue.
主要初始化了这两个数据对象,其中mConfigs用于存储属性配置,mPropertyValues用于存储属性值。
3.2 EmulatedVehicleConnector初始化
也是采用无参构造,初始化了一个对象
cpp
EmulatedUserHal mEmulatedUserHal;
3.3 EmulatedVehicleHal初始化
cpp
EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
EmulatedUserHal* emulatedUserHal = nullptr);
这个类只有一个三个参数的构造函数,第三个参数有默认值,其实现如下:
cpp
EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
EmulatedUserHal* emulatedUserHal)
: mPropStore(propStore),
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
std::placeholders::_1)),
mVehicleClient(client),
mEmulatedUserHal(emulatedUserHal) {
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));
}
这个构造函数初始化的时候传入的两个参数是在main函数中创建的VehiclePropertyStore对象和EmulatedVehicleConnector对象,而这个构造函数的第二个参数却是VehicleHalClient,这是怎么回事呢?
cpp
class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer>
template <typename VehicleClientType, typename VehicleServerType>
class IPassThroughConnector : public VehicleClientType, public VehicleServerType
从上面可以看出,EmulatedVehicleConnector继承自IPassThroughConnector,而IPassThroughConnector定义了两个模板,IPassThroughConnector继承这两个模板类。所以EmulatedVehicleConnector继承VehicleHalClient和VehicleHalServer。所以EmulatedVehicleConnector是VehicleHalClient的子类。
接着分析EmulatedVehicleHal的构造函数,这里用传入的VehiclePropertyStore对象初始化mPropStore。
cpp
std::unordered_set<int32_t> mHvacPowerProps;
const int32_t kHvacPowerProperties[] = {
toInt(VehicleProperty::HVAC_FAN_SPEED),
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
};
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties))
然后初始化这个成员变量,将数组中的两个空调相关的property的propId添加到mHvacPowerProps这个vector中。
cpp
RecurrentTimer mRecurrentTimer;
mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
std::placeholders::_1)),
RecurrentTimer(const Action& action) : mAction(action) {
mTimerThread = std::thread(&RecurrentTimer::loop, this, action);
}
这个是一个执行定时任务相关的类,初始化成员变量mRecurrentTimer为一个RecurrentTimer对象,这个对象在初始化的时候会创建一个线程,这个线程中会定时执行传入的函数。具体的分析见3.7小结。
cpp
mVehicleClient(client)
然后初始化mVehicleClient为main函数中创建的EmulatedVehicleConnector对象。
cpp
mEmulatedUserHal(emulatedUserHal)
这个使用默认参数,空指针。
cpp
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是一个定义了车辆属性配置的结构体数组,以下是其中的一个元素,表示车辆的空调温度设置的属性配置:
cpp
{.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
.areaConfigs = {VehicleAreaConfig{
.areaId = HVAC_LEFT,
.minFloatValue = 16,
.maxFloatValue = 32,
},
VehicleAreaConfig{
.areaId = HVAC_RIGHT,
.minFloatValue = 16,
.maxFloatValue = 32,
}}},
.initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}},
{HVAC_RIGHT, {.floatValues = {20}}}}},
OBD2_FREEZE_FRAME表示冻结帧,跟诊断相关,暂时不清楚,暂不看这块的处理。然后会将所有的属性配置注册到VehiclePropertyStore中。
这些属性配置就是vhal中支持的属性,如果没有在这个结构体数组中定义,则该功能不支持,供应商提供的新的需要在这个结构体中新增。
后面的for循环和initStaticConfig中的逻辑一样,跳过,这块应该没什么意义的。
cpp
mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
this, std::placeholders::_1,
std::placeholders::_2));
最后注册callback函数到EmulatedVehicleConnector对象中,回调函数是EmulatedVehicleHal::onPropertyValue。
至此,就初始化完成了,主要做的就是创建EmulatedVehicleHal对象,并且注册一些回调函数,然后比较重要的一点是加载了所有的属性配置到VehiclePropertyStore中。
3.4 VehicleEmulator初始化
cpp
VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} {
mHal->registerEmulator(this);
ALOGI("Starting SocketComm");
mSocketComm = std::make_unique<SocketComm>(this);
mSocketComm->start();
if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
ALOGI("Starting PipeComm");
mPipeComm = std::make_unique<PipeComm>(this);
mPipeComm->start();
}
}
持有EmulatedVehicleHal对象,创建SocketComm或者PipeComm,并启动,这是模拟的与VHAL连接的客户端的通信类。
3.5 VehicleHalManager初始化
cpp
VehicleHalManager(VehicleHal* vehicleHal)
: mHal(vehicleHal),
mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
this, std::placeholders::_1)) {
init();
}
先将EmulatedVehicleHal保存至mHal变量中,然后会初始化一个订阅相关的类SubscriptionManager,最后调用init函数。
SubscriptionManager初始化见3.6小节,接下来分析init函数
cpp
hidl_vec<VehiclePropValue> mHidlVecOfVehiclePropValuePool;
------------------------------------------------------------------------------------------------------------------------
void VehicleHalManager::init() {
ALOGI("VehicleHalManager::init");
//初始化mHidlVecOfVehiclePropValuePool为20,用于存储VehiclePropValue
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);
}
}
VehiclePropConfigIndex初始化见3.7小节
3.5.1 批处理初始化
cpp
ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
------------------------------------------------------------------------------------------------------------------------
mBatchingConsumer.run(&mEventQueue,
kHalEventBatchingTimeWindow,
std::bind(&VehicleHalManager::onBatchHalEvent,
this, _1));
------------------------------------------------------------------------------------------------------------------------
void run(ConcurrentQueue<T>* queue,
std::chrono::nanoseconds batchInterval,
const OnBatchReceivedFunc& func) {
mQueue = queue;
mBatchInterval = batchInterval;
mWorkerThread = std::thread(
&BatchingConsumer<T>::runInternal, this, func);
}
先看这部分代码,mQueue=mEventQueue,用于添加事件,是VehiclePropValuePtr类型事件。mBatchInterval=kHalEventBatchingTimeWindow=10,然后创建了一个线程,执行的函数是BatchingConsumer::runInternal,传入的参数是VehicleHalManager::onBatchHalEvent。
cpp
void runInternal(const OnBatchReceivedFunc& onBatchReceived) {
if (mState.exchange(State::RUNNING) == State::INIT) {
while (State::RUNNING == mState) {
mQueue->waitForItems();
if (State::STOP_REQUESTED == mState) break;
std::this_thread::sleep_for(mBatchInterval);
if (State::STOP_REQUESTED == mState) break;
std::vector<T> items = mQueue->flush();
if (items.size() > 0) {
onBatchReceived(items);
}
}
}
mState = State::STOPPED;
}
批处理这个类的主要作用就是循环执行mQueue中的事件,如果有事件到来就执行,没有就休眠。mQueue事件什么时候添加后续分析。
3.5.2 初始化现有属性值
cpp
VehiclePropValuePool mValueObjectPool;
VehiclePropValuePool(size_t maxRecyclableVectorSize = 4) :
mMaxRecyclableVectorSize(maxRecyclableVectorSize) {};
----------------------------------------------------------------------------------------------
mHal->init(&mValueObjectPool,
std::bind(&VehicleHalManager::onHalEvent, this, _1),
std::bind(&VehicleHalManager::onHalPropertySetError, this,
_1, _2, _3));
----------------------------------------------------------------------------------------------
void init(
VehiclePropValuePool* valueObjectPool,
const HalEventFunction& onHalEvent,
const HalErrorFunction& onHalError) {
mValuePool = valueObjectPool;
mOnHalEvent = onHalEvent;
mOnHalPropertySetError = onHalError;
onCreate();
}
mValuePool存储的是VehiclePropValuePool对象,是用于VehiclePropValue解析的池子,方便循环利用。mOnHalEvent是onHalEvent函数,mOnHalPropertySetError是onHalPropertySetError函数,然后调用onCreate函数。onCreate是一个虚函数,由实际的VehicleHal类实现,即EmulatedVehicleHal中的实现:
cpp
// Parse supported properties list and generate vector of property values to hold current values.
void EmulatedVehicleHal::onCreate() {
static constexpr bool shouldUpdateStatus = true;
//遍历所有的属性配置
for (auto& it : kVehicleProperties) {
VehiclePropConfig cfg = it.config;
int32_t numAreas = cfg.areaConfigs.size();
if (isDiagnosticProperty(cfg)) {
// do not write an initial empty value for the diagnostic properties
// as we will initialize those separately.
continue;
}
// A global property will have only a single area
if (isGlobalProp(cfg.prop)) {
numAreas = 1;
}
//对于分区属性的处理
for (int i = 0; i < numAreas; i++) {
int32_t curArea;
if (isGlobalProp(cfg.prop)) {
curArea = 0;
} else {
curArea = cfg.areaConfigs[i].areaId;
}
// Create a separate instance for each individual zone
//初始化VehiclePropValue
VehiclePropValue prop = {
.areaId = curArea,
.prop = cfg.prop,
};
//设置初始属性值
if (it.initialAreaValues.size() > 0) {
auto valueForAreaIt = it.initialAreaValues.find(curArea);
if (valueForAreaIt != it.initialAreaValues.end()) {
prop.value = valueForAreaIt->second;
} else {
ALOGW("%s failed to get default value for prop 0x%x area 0x%x",
__func__, cfg.prop, curArea);
}
} else {
prop.value = it.initialValue;
}
//属性值写入VehiclePropertyStore
mPropStore->writeValue(prop, shouldUpdateStatus);
}
}
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
}
这块主要就是将根据默认配置里面的属性配置,将初始化的属性值写入到VehiclePropertyStore中进行缓存。
3.6 SubscriptionManager初始化
SubscriptionManager是在VehicleHalManager中创建并持有的。
cpp
mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
this, std::placeholders::_1))
----------------------------------------------------------------------------------------------
SubscriptionManager(const OnPropertyUnsubscribed& onPropertyUnsubscribed)
: mOnPropertyUnsubscribed(onPropertyUnsubscribed),
mCallbackDeathRecipient(new DeathRecipient(
std::bind(&SubscriptionManager::onCallbackDead, this, std::placeholders::_1)))
{}
传入的参数是一个函数,保存在mOnPropertyUnsubscribed中,并初始化mCallbackDeathRecipient为一个DeathRecipient对象,这个对象构造时的参数为onCallbackDead函数。
cpp
DeathRecipient(const OnClientDead& onClientDead)
: mOnClientDead(onClientDead) {}
onCallbackDead保存在mOnClientDead中。
VehicleHalManager中创建SubscriptionManager对象,并对其进行管理。
3.7 RecurrentTimer初始化
RecurrentTimer由EmulatedVehicleHal的构造函数初始化,并适时回调EmulatedVehicleHal中的回调函数。
cpp
RecurrentTimer mRecurrentTimer;
mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
std::placeholders::_1)),
RecurrentTimer(const Action& action) : mAction(action) {
mTimerThread = std::thread(&RecurrentTimer::loop, this, action);
}
using Action = std::function<void(const std::vector<int32_t>& cookies)>;
接着3.3节中分析,RecurrentTimer对象创建后,赋值给mRecurrentTimer。RecurrentTimer创建时,传入的参数是一个function类型数据,包含的是一个函数。EmulatedVehicleHal::onContinuousPropertyTimer,bind函数的第二个参数传入this,因为是一个成员函数,然后是一个参数占位符,因为该函数需要传入一个参数。
然后RecurrentTimer的构造函数中,创建了一个线程,执行的函数是RecurrentTimer::loop,传入的参数是Action对象,即onContinuousPropertyTimer
cpp
void loop(const Action& action) {
static constexpr auto kInvalidTime = TimePoint(Nanos::max());
std::vector<int32_t> cookies;
while (!mStopRequested) {
auto now = Clock::now();
auto nextEventTime = kInvalidTime;
cookies.clear();
{
std::unique_lock<std::mutex> g(mLock);
for (auto&& it : mCookieToEventsMap) {
//获取定时上报事件
RecurrentEvent& event = it.second;
if (event.absoluteTime <= now) {
event.updateNextEventTime(now);
cookies.push_back(event.cookie);
}
if (nextEventTime > event.absoluteTime) {
nextEventTime = event.absoluteTime;
}
}
}
if (cookies.size() != 0) {
action(cookies);
}
std::unique_lock<std::mutex> g(mLock);
mCond.wait_until(g, nextEventTime); // nextEventTime can be nanoseconds::max()
}
}
mStopRequested没有其他地方赋值,有默认值为false,所以会进入while循环。
这里主要是定时事件上报的处理逻辑,如果到时间了,就会加入到cookies这个变量中,并调用action这个回到函数,即onContinuousPropertyTimer这个回调函数去处理所有到时间的定时事件。
4 初始化流程图
plantuml代码:
cpp
@startuml
participant init
box
participant VehicleService
participant VehicleHalManager
participant VehicleEmulator
participant EmulatedVehicleHal
participant EmulatedVehicleConnector
participant VehiclePropertyStore
participant SocketComm
participant SubscriptionManager
participant DeathRecipient
participant BatchingConsumer
endbox
init -> VehicleService: 拉起服务
VehicleService -> VehiclePropertyStore: new VehiclePropertyStore()
VehicleService -> EmulatedVehicleConnector: new EmulatedVehicleConnector()
VehicleService -> EmulatedVehicleHal: new EmulatedVehicleHal(VehiclePropertyStore* propStore, \n\tVehicleHalClient* client, EmulatedUserHal* emulatedUserHal = nullptr);
EmulatedVehicleHal -> EmulatedVehicleHal: initStaticConfig()
EmulatedVehicleHal -> VehiclePropertyStore: registerProperty(const VehiclePropConfig& config, \n\tVehiclePropertyStore::TokenFunction tokenFunc)
EmulatedVehicleHal -> EmulatedVehicleConnector: registerPropertyValueCallback(PropertyCallBackType&& callback)
VehicleService -> VehicleEmulator: new VehicleEmulator(EmulatedVehicleHalIface* hal)
VehicleEmulator -> EmulatedVehicleHal: registerEmulator(this)
VehicleEmulator -> SocketComm: start()
VehicleService -> VehicleHalManager: new VehicleHalManager(VehicleHal* vehicleHal)
VehicleHalManager -> SubscriptionManager: new (const OnPropertyUnsubscribed& onPropertyUnsubscribed\n\t: mOnPropertyUnsubscribed(onPropertyUnsubscribed),\n\tmCallbackDeathRecipient(new DeathRecipient(\n\tstd::bind(&SubscriptionManager::onCallbackDead, this, std::placeholders::_1)))
SubscriptionManager -> DeathRecipient: new DeathRecipient(const OnClientDead& onClientDead)
VehicleHalManager -> VehicleHalManager: init()
VehicleHalManager -> BatchingConsumer: run()
loop
BatchingConsumer -> BatchingConsumer: runInternal(const OnBatchReceivedFunc& onBatchReceived)
end loop
VehicleHalManager -> EmulatedVehicleHal: init( \n\tVehiclePropValuePool* valueObjectPool, \n\tconst HalEventFunction& onHalEvent, \n\tconst HalErrorFunction& onHalError)
EmulatedVehicleHal -> EmulatedVehicleHal: onCreate()
EmulatedVehicleHal -> VehiclePropertyStore: writeValue(const VehiclePropValue& propValue, bool updateStatus)
VehicleService -> EmulatedVehicleConnector: setValuePool(VehiclePropValuePool* valuePool)
VehicleService -> VehicleHalManager: registerAsService()
@enduml
流程图