get
HIDL实现
时序图
sequenceDiagram
participant CS as CarService
participant VHM as VehicleHalManager
participant VH as XXXVehicleHal
participant VPS as VehiclePropertyStore
participant VOP as VehiclePropValuePool
autonumber
CS ->>+ VHM : get
VHM->>VH: get
VH->>VPS: readValueOrNull
VPS->>VPS: getRecordIdLocked
VPS->>VPS: readValueOrNull
VPS->>VPS: getValueOrNullLocked
VPS-->>VH: std::unique_ptr<VehiclePropValue>
VH->>VOP: obtain
VOP-->>VH: VehiclePropValuePtr
VH-->>VHM: VehiclePropValuePtr
VHM-->>CS: StatusCode, VehiclePropValue
具体流程
step 1 调用get方法,这一步会向下调用VehicleHal的get方法,并通过_hidl_cb返回StatusCode和VehiclePropValue
Return<void> VehicleHalManager::get(const VehiclePropValue& requestedPropValue, get_cb _hidl_cb) {
//根据配置进行一些检查
...
StatusCode status;
//调用VehicleHal的get方法
auto value = mHal->get(requestedPropValue, &status);
_hidl_cb(status, value.get() ? *value : kEmptyValue);
return Void();
}
step 2 这一步会先调用VehiclePropertyStore的readValueOrNull方法,获取一个指向VehiclePropertyValue的唯一指针,然后调用VehiclePropValuePool::obtain方法进行对象复用
VehicleHal::VehiclePropValuePtr XXXVehicleHal::get(
const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
auto propId = requestedPropValue.prop;
...
auto& pool = *getValuePool();
VehiclePropValuePtr v = nullptr;
switch (propId) {
...
default:
...
//从VehiclePropertyStore中读取值
auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
//通过VehicleObjectPool进行对象复用
if (internalPropValue != nullptr) {
v = getValuePool()->obtain(*internalPropValue);
}
*outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
break;
}
if (v.get()) {
v->timestamp = elapsedRealtimeNano();
}
return v;
}
step 3 这一步首先会获取record id, record id由property id, area id 和 token三部分组成:
std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
const VehiclePropValue& request) const {
MuxGuard g(mLock);
//首先找到request对应的record id
RecordId recId = getRecordIdLocked(request);
//然后根据record id获取值
const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}
step 4 获取record id 时会向本地的configs中查询是否由property id对应的config,如果没有则返回空,否则设置token。
VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
const VehiclePropValue& valuePrototype) const {
RecordId recId = {
.prop = valuePrototype.prop,
.area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
.token = 0
};
auto it = mConfigs.find(recId.prop);
if (it == mConfigs.end()) return {};
if (it->second.tokenFunction != nullptr) {
recId.token = it->second.tokenFunction(valuePrototype);
}
return recId;
}
step 5 获取到record id后,会根据record id调用getValueOrNullLocked,获取属性值并返回。
std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
int32_t prop, int32_t area, int64_t token) const {
RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
MuxGuard g(mLock);
const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}
step 6 getValueOrNullLocked方法会从mProertyValues中找到对应的value并返回。
const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
const VehiclePropertyStore::RecordId& recId) const {
auto it = mPropertyValues.find(recId);
return it == mPropertyValues.end() ? nullptr : &it->second;
}
step 7 这一步通过VehiclePropValuePool::obtain方法从对象池中返回一个可用的对象。
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
const VehiclePropValue& src) {
...
VehiclePropertyType type = getPropType(src.prop);
size_t vecSize = getVehicleRawValueVectorSize(src.value, type);;
auto dest = obtain(type, vecSize);
dest->prop = src.prop;
dest->areaId = src.areaId;
dest->status = src.status;
dest->timestamp = src.timestamp;
copyVehicleRawValue(&dest->value, src.value);
return dest;
}
对象复用
对于VehiclePropValuePool::obtain方法,其会通过type和vecSize从对象池中获取一个可复用的对象:
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
VehiclePropertyType type, size_t vecSize) {
return isDisposable(type, vecSize)
? obtainDisposable(type, vecSize)
: obtainRecylable(type, vecSize);
}
,会根据type和vecSize判断是不是可以复用的:
bool isDisposable(VehiclePropertyType type, size_t vecSize) const {
return vecSize > mMaxRecyclableVectorSize || VehiclePropertyType::STRING == type ||
VehiclePropertyType::MIXED == type;
}
,如果vecSize过大,或者其类型为String或者MIXED,则不可复用。
如果对象可以复用,那么这一步就会从mValueTypePools中获取一个对象池(没有则创建),然后从对象池中获取一个可以复用的对象:
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecylable(
VehiclePropertyType type, size_t vecSize) {
int32_t key = static_cast<int32_t>(type)
| static_cast<int32_t>(vecSize);
std::lock_guard<std::mutex> g(mLock);
auto it = mValueTypePools.find(key);
if (it == mValueTypePools.end()) {
auto newPool(std::make_unique<InternalPool>(type, vecSize));
it = mValueTypePools.emplace(key, std::move(newPool)).first;
}
return it->second->obtain();
}
如果对象不可以复用,则直接创建一个对象,该对象在被delete时直接销毁:
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
VehiclePropertyType valueType, size_t vectorSize) const {
return RecyclableType {
createVehiclePropValue(valueType, vectorSize).release(),
mDisposableDeleter
};
}
查看ObjectPool的定义,在进行obtain时,其会从mObjects中获取一个unique_ptr,然后通过wrap方法进行包装,而wrap方法会给unique_ptr新增一个Deleter,在对象被销毁时,调用recycle方法,这个方法会将对象重新放回到mObjects中。
template <typename T>
using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
template<typename T>
class ObjectPool {
public:
ObjectPool() = default;
virtual ~ObjectPool() = default;
virtual recyclable_ptr<T> obtain() {
std::lock_guard<std::mutex> g(mLock);
...
auto o = wrap(mObjects.front().release());
mObjects.pop_front();
return o;
}
ObjectPool& operator =(const ObjectPool &) = delete;
ObjectPool(const ObjectPool &) = delete;
protected:
...
virtual void recycle(T* o) {
...
mObjects.push_back(std::unique_ptr<T> { o } );
}
private:
const Deleter<T>& getDeleter() {
if (!mDeleter.get()) {
Deleter<T> *d = new Deleter<T>(std::bind(
&ObjectPool::recycle, this, std::placeholders::_1));
mDeleter.reset(d);
}
return *mDeleter.get();
}
recyclable_ptr<T> wrap(T* raw) {
return recyclable_ptr<T> { raw, getDeleter() };
}
private:
mutable std::mutex mLock;
std::deque<std::unique_ptr<T>> mObjects;
std::unique_ptr<Deleter<T>> mDeleter;
};
VehiclePropertyStore中始终存储最新值
在XXXVehicleHal中存在如下方法,用于给下层在属性值改变时进行调用,可以看到,当下层通知属性值改变时,XXXVehicleHal就会将新值写入到VehiclePropertyStore中,保证get调用获取的始终是最新值。
void XXXVehicleHal::onPropertyValue(const VehiclePropValue &value, bool updateStatus)
{
VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
if (mPropStore->writeValue(*updatedPropValue, updateStatus))
{
...
}
}
AIDL实现
时序图
sequenceDiagram
participant CS as CarService
participant VH as XXXVehicleHal
participant VHw as XXXVehicleHalware
participant H as PendingRequestHandler
participant VPS as VehiclePropertyStore
CS->>+VH : getValues
par
activate VH
VH->>VH: getOrCreateClient
deactivate VH
VH->>+VHw: getValues
deactivate VH
VHw->>+H: addRequest
deactivate VHw
deactivate H
and
activate H
H->>H:handleRequestOnce
H->>+VHw: handleGetValueRequest
activate VHw
VHw->>VHw:getValue
VHw->>+VPS: readValue
activate VPS
VPS->>VPS: readValueLocked
VPS-->>VHw: propertyValue
deactivate VPS
VHw-->>H: propertyValue
deactivate VHw
deactivate VHw
end
H-->>CS: callback
deactivate H
详细步骤
step 1 在AIDL实现中,Vhal允许多个get请求合并并通过异步的方式返回,于是在第一步,会根据callback创建对应的client用于记录get属性的callback对象。然后将get请求传递给VehicleHardware:
ScopedAStatus XXXVehicleHal::getValues(const CallbackType& callback,
const GetValueRequests& requests) {
...
std::vector<GetValueRequest> hardwareRequests;
...
std::shared_ptr<GetValuesClient> client;
{
...
client = getOrCreateClient(&mGetValuesClients, callback, mPendingRequestPool);
}
...
if (StatusCode status =
mVehicleHardware->getValues(client->getResultCallback(), hardwareRequests);
status != StatusCode::OK) {
...
}
return ScopedAStatus::ok();
}
step 2 收到get请求后,VehicleHardware需要记录每个get请求对应的callback用于当请求收到响应时进行回调:
StatusCode XXXVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback,
const std::vector<GetValueRequest>& requests) const {
for (auto& request : requests) {
...
mPendingGetValueRequests.addRequest(request, callback);
}
return StatusCode::OK;
}
step 3 PendingRequestHandler的addRequest方法则是将request和callback存入一个map中:
template <class CallbackType, class RequestType>
void XXXVehicleHardware::PendingRequestHandler<CallbackType, RequestType>::addRequest(
RequestType request, std::shared_ptr<const CallbackType> callback) {
mRequests.push({
request,
callback,
});
}
step 4 在PendingRequestHandler创建时,会通过一个thread执行handleRequestOnce方法用于异步处理get请求。方法首先会从map不断取出request,执行VehicleHardware::handleGetValueRequest方法,然后调用callback用于返回get响应:
template <>
void XXXeVehicleHardware::PendingRequestHandler<FakeVehicleHardware::GetValuesCallback,
GetValueRequest>::handleRequestsOnce() {
std::unordered_map<std::shared_ptr<const GetValuesCallback>, std::vector<GetValueResult>>
callbackToResults;
for (const auto& rwc : mRequests.flush()) {
...
auto result = mHardware->handleGetValueRequest(rwc.request);
...
}
for (const auto& [callback, results] : callbackToResults) {
...
(*callback)(std::move(results));
...
}
}
step 5 实际执行getValue方法,获取最新值并返回:
GetValueResult XXXVehicleHardware::handleGetValueRequest(const GetValueRequest& request) {
GetValueResult getValueResult;
getValueResult.requestId = request.requestId;
auto result = getValue(request.prop);
...
return getValueResult;
}
step 6 方法从VehiclePropertyStore中读取属性值并返回:
XXXVehicleHardware::ValueResultType XXXVehicleHardware::getValue(
const VehiclePropValue& value) const {
...
auto readResult = mServerSidePropStore->readValue(value);
...
return std::move(readResult);
}
step 7 readValue方法根据属性的找到对应的record 和recordId,并执行readValueLocked方法:
VehiclePropertyStore::ValueResultType VehiclePropertyStore::readValue(
const VehiclePropValue& propValue) const {
std::scoped_lock<std::mutex> g(mLock);
int32_t propId = propValue.prop;
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
...
VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
return readValueLocked(recId, *record);
}
在AIDL实现的VehiclePropertyStore中,属性值与属性的存储方式如下:
step 8 这一步会从record中根据recordId找到对应的value,并通过VehiclePropValuePool进行对象复用:
VhalResult<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValueLocked(
const RecordId& recId, const Record& record) const REQUIRES(mLock) {
if (auto it = record.values.find(recId); it != record.values.end()) {
return mValuePool->obtain(*(it->second));
}
...
}
set
HIDL实现
时序图
sequenceDiagram
participant CS as CarService
participant VHM as VehicleHalManager
participant VH as XXXVehicleHal
participant Hw as Connector/others
CS->>VHM: set
VHM->>VHM: handlePropertySetEvent
VHM->>VH: set
VH->>Hw: set value
详细步骤
step 1 第一步首先会调用自己的handlePropertySetEvent方法,然后将set请求传递到下层:
Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {
auto prop = value.prop;
...
handlePropertySetEvent(value);
auto status = mHal->set(value);
return Return<StatusCode>(status);
}
step 2 这一步主要会回调订阅了属性的EVENTS_FROM_ANDROID事件的callback:
void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
auto clients =
mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::EVENTS_FROM_ANDROID);
for (const auto& client : clients) {
client->getCallback()->onPropertySet(value);
}
}
step 3 这一步会首先从VehiclePropertyStore中读取属性的当前值,然后进行一些下层调用:
StatusCode XXXVehicleHal::set(const VehiclePropValue &propValue)
{
constexpr bool updateStatus = false;
...
auto currentPropValue = mPropStore->readValueOrNull(propValue);
...
/**
* 这里需要实现与硬件的交互
*/
return StatusCode::OK;
}
AIDL实现
时序图
sequenceDiagram
participant CS as CarService
participant VH as XXXVehicleHal
participant VHw as XXXVehicleHalware
participant H as PendingRequestHandler
participant VPVP as VehiclePropValuePool
participant VPS as VehiclePropertyStore
CS->>+VH : setValues
par
activate VH
VH->>VH: getOrCreateClient
deactivate VH
VH->>+VHw: setValues
deactivate VH
VHw->>+H: addRequest
deactivate VHw
deactivate H
and
activate H
H->>H:handleRequestOnce
H->>+VHw: handleSetValueRequest
activate VHw
VHw->>VHw:setValue
VHw->>+VPVP: obtain
VPVP-->>VHw: recyclable property value
deactivate VPVP
VHw->>+VPS: writeValue
deactivate VPS
VHw-->>H: {}
deactivate VHw
deactivate VHw
end
H-->>CS: callback
deactivate H
详细步骤
step 1 set请求允许多个请求合并,并异步执行,然后通过callback返回set响应。与get相同,这一步也会首先创建一个对应的client用于记录一个callback上的不同get请求。然后,向下层传递set请求:
ScopedAStatus XXXVehicleHal::setValues(const CallbackType& callback,
const SetValueRequests& requests) {
...
std::vector<SetValueRequest> hardwareRequests;
...
std::unordered_set<int64_t> hardwareRequestIds;
for (const auto& request : hardwareRequests) {
hardwareRequestIds.insert(request.requestId);
}
std::shared_ptr<SetValuesClient> client;
{
...
client = getOrCreateClient(&mSetValuesClients, callback, mPendingRequestPool);
}
...
if (StatusCode status =
mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
status != StatusCode::OK) {
...
}
return ScopedAStatus::ok();
}
step 2 与get类似,这一步会将set请求放到一个等待队列中:
StatusCode XXXVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback,
const std::vector<SetValueRequest>& requests) {
for (auto& request : requests) {
mPendingSetValueRequests.addRequest(request, callback);
}
return StatusCode::OK;
}
step 3 与get类似,这一步会从等待队列中取出所有的set请求,并执行handleSetValueRequest方法,然后回调callback:
void XXXVehicleHardware::PendingRequestHandler<FakeVehicleHardware::SetValuesCallback,
SetValueRequest>::handleRequestsOnce() {
std::unordered_map<std::shared_ptr<const SetValuesCallback>, std::vector<SetValueResult>>
callbackToResults;
for (const auto& rwc : mRequests.flush()) {
...
auto result = mHardware->handleSetValueRequest(rwc.request);
...
}
for (const auto& [callback, results] : callbackToResults) {
...
(*callback)(std::move(results));
...
}
}
step 4 这一步实际调用了setValue方法:
SetValueResult XXXVehicleHardware::handleSetValueRequest(const SetValueRequest& request) {
SetValueResult setValueResult;
setValueResult.requestId = request.requestId;
if (auto result = setValue(request.value); !result.ok()) {
...
} else {
...
}
return setValueResult;
}
step 5 可以看到setValue方法首先会调用VehiclePropValuePool的obtain方法返回一个复用的对象,然后写入到VehiclePropertyStore中,保证了get可以始终获取最新值。最后执行一些下层的操作。
VhalResult<void> XXXVehicleHardware::setValue(const VehiclePropValue& value) {
...
auto updatedValue = mValuePool->obtain(value);
int64_t timestamp = elapsedRealtimeNano();
updatedValue->timestamp = timestamp;
auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue));
...
//执行一些与硬件交互
return {};
}