Loading automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h +9 −9 Original line number Diff line number Diff line Loading @@ -123,10 +123,10 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi std::shared_ptr<PendingRequestPool> mPendingRequestPool; }; // A wrapper for binder operations to enable stubbing for test. class IBinder { // A wrapper for binder lifecycle operations to enable stubbing for test. class BinderLifecycleInterface { public: virtual ~IBinder() = default; virtual ~BinderLifecycleInterface() = default; virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) = 0; Loading @@ -134,8 +134,8 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi virtual bool isAlive(const AIBinder* binder) = 0; }; // A real implementation for IBinder. class AIBinderImpl final : public IBinder { // A real implementation for BinderLifecycleInterface. class BinderLifecycleHandler final : public BinderLifecycleInterface { public: binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) override; Loading @@ -154,7 +154,7 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi // BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event. struct BinderDiedUnlinkedEvent { // true for onBinderDied, false for onBinderUnlinked. bool onBinderDied; bool forOnBinderDied; const AIBinder* clientId; }; Loading Loading @@ -186,8 +186,8 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi GUARDED_BY(mLock); // SubscriptionClients is thread-safe. std::shared_ptr<SubscriptionClients> mSubscriptionClients; // mBinderImpl is only going to be changed in test. std::unique_ptr<IBinder> mBinderImpl; // mBinderLifecycleHandler is only going to be changed in test. std::unique_ptr<BinderLifecycleInterface> mBinderLifecycleHandler; // Only initialized once. std::shared_ptr<std::function<void()>> mRecurrentAction; Loading Loading @@ -263,7 +263,7 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi void setTimeout(int64_t timeoutInNano); // Test-only void setBinderImpl(std::unique_ptr<IBinder> impl); void setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> impl); }; } // namespace vehicle Loading automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h +16 −17 Original line number Diff line number Diff line Loading @@ -41,15 +41,15 @@ class ContSubConfigs final { public: using ClientIdType = const AIBinder*; void addClient(const ClientIdType& clientId, float sampleRate); void addClient(const ClientIdType& clientId, float sampleRateHz); void removeClient(const ClientIdType& clientId); float getMaxSampleRate(); float getMaxSampleRateHz() const; private: float mMaxSampleRate = 0.; std::unordered_map<ClientIdType, float> mSampleRates; float mMaxSampleRateHz = 0.; std::unordered_map<ClientIdType, float> mSampleRateHzByClient; void refreshMaxSampleRate(); void refreshMaxSampleRateHz(); }; // A thread-safe subscription manager that manages all VHAL subscriptions. Loading @@ -59,7 +59,7 @@ class SubscriptionManager final { using CallbackType = std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>; explicit SubscriptionManager(IVehicleHardware* hardware); explicit SubscriptionManager(IVehicleHardware* vehicleHardware); ~SubscriptionManager(); // Subscribes to properties according to {@code SubscribeOptions}. Note that all option must Loading Loading @@ -99,13 +99,8 @@ class SubscriptionManager final { const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>& updatedValues); // Gets the sample rate for the continuous property. Returns {@code std::nullopt} if the // property has not been subscribed before or is not a continuous property. std::optional<float> getSampleRate(const ClientIdType& clientId, int32_t propId, int32_t areaId); // Checks whether the sample rate is valid. static bool checkSampleRate(float sampleRate); static bool checkSampleRateHz(float sampleRateHz); private: // Friend class for testing. Loading @@ -122,17 +117,21 @@ class SubscriptionManager final { std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea GUARDED_BY(mLock); VhalResult<void> updateSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRate) VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz) REQUIRES(mLock); VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) REQUIRES(mLock); VhalResult<void> removeSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) REQUIRES(mLock); VhalResult<void> updateContSubConfigs(const PropIdAreaId& PropIdAreaId, const ContSubConfigs& newConfig) REQUIRES(mLock); // Checks whether the manager is empty. For testing purpose. bool isEmpty(); // Get the interval in nanoseconds accroding to sample rate. static android::base::Result<int64_t> getInterval(float sampleRate); static android::base::Result<int64_t> getIntervalNanos(float sampleRateHz); }; } // namespace vehicle Loading automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp +51 −48 Original line number Diff line number Diff line Loading @@ -78,14 +78,14 @@ std::string toString(const std::unordered_set<int64_t>& values) { return str; } float getDefaultSampleRate(float sampleRate, float minSampleRate, float maxSampleRate) { if (sampleRate < minSampleRate) { return minSampleRate; float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) { if (sampleRateHz < minSampleRateHz) { return minSampleRateHz; } if (sampleRate > maxSampleRate) { return maxSampleRate; if (sampleRateHz > maxSampleRateHz) { return maxSampleRateHz; } return sampleRate; return sampleRateHz; } } // namespace Loading Loading @@ -123,8 +123,8 @@ size_t DefaultVehicleHal::SubscriptionClients::countClients() { return mClients.size(); } DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) : mVehicleHardware(std::move(hardware)), DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware) : mVehicleHardware(std::move(vehicleHardware)), mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) { auto configs = mVehicleHardware->getAllPropertyConfigs(); for (auto& config : configs) { Loading @@ -143,12 +143,11 @@ DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) mConfigFile = std::move(result.value()); } mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool); mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool); auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>(); IVehicleHardware* hardwarePtr = mVehicleHardware.get(); mSubscriptionManager = std::make_shared<SubscriptionManager>(hardwarePtr); IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get(); mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr); std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager; mVehicleHardware->registerOnPropertyChangeEvent( Loading @@ -158,13 +157,13 @@ DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) })); // Register heartbeat event. mRecurrentAction = std::make_shared<std::function<void()>>([hardwarePtr, subscriptionManagerCopy]() { checkHealth(hardwarePtr, subscriptionManagerCopy); mRecurrentAction = std::make_shared<std::function<void()>>( [vehicleHardwarePtr, subscriptionManagerCopy]() { checkHealth(vehicleHardwarePtr, subscriptionManagerCopy); }); mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction); mBinderImpl = std::make_unique<AIBinderImpl>(); mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>(); mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); }); mDeathRecipient = ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied)); Loading Loading @@ -220,7 +219,7 @@ std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient( bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) { OnBinderDiedContext* contextPtr = nullptr; if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) { return mBinderImpl->isAlive(clientId); return mBinderLifecycleHandler->isAlive(clientId); } else { std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>( OnBinderDiedContext{.vhal = this, .clientId = clientId}); Loading @@ -232,7 +231,7 @@ bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) { } // If this function fails, onBinderUnlinked would be called to remove the added context. binder_status_t status = mBinderImpl->linkToDeath( binder_status_t status = mBinderLifecycleHandler->linkToDeath( const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr)); if (status == STATUS_OK) { return true; Loading @@ -246,7 +245,8 @@ void DefaultVehicleHal::onBinderDied(void* cookie) { OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie); // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same // thread because we might be holding the mLock the handler requires. context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{true, context->clientId}); context->vhal->mBinderEvents.push( BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId}); } void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) { Loading @@ -262,7 +262,8 @@ void DefaultVehicleHal::onBinderUnlinked(void* cookie) { OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie); // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same // thread because we might be holding the mLock the handler requires. context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{false, context->clientId}); context->vhal->mBinderEvents.push( BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId}); } void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) { Loading @@ -275,7 +276,7 @@ void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) { void DefaultVehicleHal::onBinderDiedUnlinkedHandler() { while (mBinderEvents.waitForItems()) { for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) { if (event.onBinderDied) { if (event.forOnBinderDied) { onBinderDiedWithContext(event.clientId); } else { onBinderUnlinkedWithContext(event.clientId); Loading Loading @@ -349,15 +350,15 @@ Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback, const GetValueRequests& requests) { if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests); if (!deserializedResults.ok()) { ALOGE("getValues: failed to parse getValues requests"); return std::move(deserializedResults.error()); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } const std::vector<GetValueRequest>& getValueRequests = deserializedResults.value().getObject()->payloads; Loading Loading @@ -435,15 +436,15 @@ ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback, ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback, const SetValueRequests& requests) { if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests); if (!deserializedResults.ok()) { ALOGE("setValues: failed to parse setValues requests"); return std::move(deserializedResults.error()); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } const std::vector<SetValueRequest>& setValueRequests = deserializedResults.value().getObject()->payloads; Loading Loading @@ -595,18 +596,20 @@ VhalResult<void> DefaultVehicleHal::checkSubscribeOptions( } if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { float sampleRate = option.sampleRate; float minSampleRate = config.minSampleRate; float maxSampleRate = config.maxSampleRate; if (sampleRate < minSampleRate || sampleRate > maxSampleRate) { float defaultRate = getDefaultSampleRate(sampleRate, minSampleRate, maxSampleRate); ALOGW("sample rate: %f out of range, must be within %f and %f, set to %f", sampleRate, minSampleRate, maxSampleRate, defaultRate); sampleRate = defaultRate; } if (!SubscriptionManager::checkSampleRate(sampleRate)) { float sampleRateHz = option.sampleRate; float minSampleRateHz = config.minSampleRate; float maxSampleRateHz = config.maxSampleRate; float defaultRateHz = getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz); if (sampleRateHz != defaultRateHz) { ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f " "HZ", sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz); sampleRateHz = defaultRateHz; } if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) { return StatusError(StatusCode::INVALID_ARG) << "invalid sample rate: " << sampleRate; << "invalid sample rate: " << sampleRateHz << " HZ"; } } Loading @@ -631,13 +634,13 @@ ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, const std::vector<SubscribeOptions>& options, [[maybe_unused]] int32_t maxSharedMemoryFileCount) { // TODO(b/205189110): Use shared memory file count. if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } if (auto result = checkSubscribeOptions(options); !result.ok()) { ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str()); return toScopedAStatus(result); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } std::vector<SubscribeOptions> onChangeSubscriptions; std::vector<SubscribeOptions> continuousSubscriptions; for (const auto& option : options) { Loading @@ -658,7 +661,7 @@ ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, } if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { optionCopy.sampleRate = getDefaultSampleRate( optionCopy.sampleRate = getDefaultSampleRateHz( optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate); continuousSubscriptions.push_back(std::move(optionCopy)); } else { Loading Loading @@ -740,9 +743,9 @@ VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& return {}; } void DefaultVehicleHal::checkHealth(IVehicleHardware* hardware, void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware, std::weak_ptr<SubscriptionManager> subscriptionManager) { StatusCode status = hardware->checkHealth(); StatusCode status = vehicleHardware->checkHealth(); if (status != StatusCode::OK) { ALOGE("VHAL check health returns non-okay status"); return; Loading @@ -757,18 +760,18 @@ void DefaultVehicleHal::checkHealth(IVehicleHardware* hardware, return; } binder_status_t DefaultVehicleHal::AIBinderImpl::linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath( AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { return AIBinder_linkToDeath(binder, recipient, cookie); } bool DefaultVehicleHal::AIBinderImpl::isAlive(const AIBinder* binder) { bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) { return AIBinder_isAlive(binder); } void DefaultVehicleHal::setBinderImpl(std::unique_ptr<IBinder> impl) { mBinderImpl = std::move(impl); void DefaultVehicleHal::setBinderLifecycleHandler( std::unique_ptr<BinderLifecycleInterface> handler) { mBinderLifecycleHandler = std::move(handler); } bool DefaultVehicleHal::checkDumpPermission() { Loading automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp +53 −65 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ using ::android::base::Result; using ::android::base::StringPrintf; using ::ndk::ScopedAStatus; SubscriptionManager::SubscriptionManager(IVehicleHardware* hardware) : mVehicleHardware(hardware) {} SubscriptionManager::SubscriptionManager(IVehicleHardware* vehicleHardware) : mVehicleHardware(vehicleHardware) {} SubscriptionManager::~SubscriptionManager() { std::scoped_lock<std::mutex> lockGuard(mLock); Loading @@ -51,94 +52,82 @@ SubscriptionManager::~SubscriptionManager() { mSubscribedPropsByClient.clear(); } bool SubscriptionManager::checkSampleRate(float sampleRate) { return getInterval(sampleRate).ok(); bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) { return getIntervalNanos(sampleRateHz).ok(); } Result<int64_t> SubscriptionManager::getInterval(float sampleRate) { int64_t interval = 0; if (sampleRate <= 0) { Result<int64_t> SubscriptionManager::getIntervalNanos(float sampleRateHz) { int64_t intervalNanos = 0; if (sampleRateHz <= 0) { return Error() << "invalid sample rate, must be a positive number"; } if (sampleRate <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) { return Error() << "invalid sample rate: " << sampleRate << ", too small"; if (sampleRateHz <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) { return Error() << "invalid sample rate: " << sampleRateHz << ", too small"; } interval = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRate); return interval; intervalNanos = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRateHz); return intervalNanos; } void ContSubConfigs::refreshMaxSampleRate() { float maxSampleRate = 0.; void ContSubConfigs::refreshMaxSampleRateHz() { float maxSampleRateHz = 0.; // This is not called frequently so a brute-focre is okay. More efficient way exists but this // is simpler. for (const auto& [_, sampleRate] : mSampleRates) { if (sampleRate > maxSampleRate) { maxSampleRate = sampleRate; for (const auto& [_, sampleRateHz] : mSampleRateHzByClient) { if (sampleRateHz > maxSampleRateHz) { maxSampleRateHz = sampleRateHz; } } mMaxSampleRate = maxSampleRate; mMaxSampleRateHz = maxSampleRateHz; } void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRate) { mSampleRates[clientId] = sampleRate; refreshMaxSampleRate(); void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRateHz) { mSampleRateHzByClient[clientId] = sampleRateHz; refreshMaxSampleRateHz(); } void ContSubConfigs::removeClient(const ClientIdType& clientId) { mSampleRates.erase(clientId); refreshMaxSampleRate(); mSampleRateHzByClient.erase(clientId); refreshMaxSampleRateHz(); } float ContSubConfigs::getMaxSampleRate() { return mMaxSampleRate; float ContSubConfigs::getMaxSampleRateHz() const { return mMaxSampleRateHz; } VhalResult<void> SubscriptionManager::updateSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRate) { VhalResult<void> SubscriptionManager::addContinuousSubscriberLocked( const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz) { // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId]; infoCopy.addClient(clientId, sampleRate); if (infoCopy.getMaxSampleRate() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) { mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; return {}; } float newRate = infoCopy.getMaxSampleRate(); int32_t propId = propIdAreaId.propId; int32_t areaId = propIdAreaId.areaId; if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate); status != StatusCode::OK) { return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32 ", area" ": %" PRId32 ", sample rate: %f", propId, areaId, newRate); } mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; return {}; ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; newConfig.addClient(clientId, sampleRateHz); return updateContSubConfigs(propIdAreaId, newConfig); } VhalResult<void> SubscriptionManager::removeSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) { VhalResult<void> SubscriptionManager::removeContinuousSubscriberLocked( const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) { // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId]; infoCopy.removeClient(clientId); if (infoCopy.getMaxSampleRate() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) { mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; newConfig.removeClient(clientId); return updateContSubConfigs(propIdAreaId, newConfig); } VhalResult<void> SubscriptionManager::updateContSubConfigs(const PropIdAreaId& propIdAreaId, const ContSubConfigs& newConfig) { if (newConfig.getMaxSampleRateHz() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRateHz()) { mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; return {}; } float newRate = infoCopy.getMaxSampleRate(); float newRateHz = newConfig.getMaxSampleRateHz(); int32_t propId = propIdAreaId.propId; int32_t areaId = propIdAreaId.areaId; if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate); if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRateHz); status != StatusCode::OK) { return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32 ", area" ": %" PRId32 ", sample rate: %f", propId, areaId, newRate); ": %" PRId32 ", sample rate: %f HZ", propId, areaId, newRateHz); } mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; return {}; } Loading @@ -147,14 +136,12 @@ VhalResult<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCa bool isContinuousProperty) { std::scoped_lock<std::mutex> lockGuard(mLock); std::vector<int64_t> intervals; for (const auto& option : options) { float sampleRate = option.sampleRate; float sampleRateHz = option.sampleRate; if (isContinuousProperty) { auto intervalResult = getInterval(sampleRate); if (!intervalResult.ok()) { return StatusError(StatusCode::INVALID_ARG) << intervalResult.error().message(); if (auto result = getIntervalNanos(sampleRateHz); !result.ok()) { return StatusError(StatusCode::INVALID_ARG) << result.error().message(); } } Loading @@ -176,7 +163,8 @@ VhalResult<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCa .areaId = areaId, }; if (isContinuousProperty) { if (auto result = updateSampleRateLocked(clientId, propIdAreaId, option.sampleRate); if (auto result = addContinuousSubscriberLocked(clientId, propIdAreaId, option.sampleRate); !result.ok()) { return result; } Loading Loading @@ -214,7 +202,7 @@ VhalResult<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdT while (it != propIdAreaIds.end()) { int32_t propId = it->propId; if (std::find(propIds.begin(), propIds.end(), propId) != propIds.end()) { if (auto result = removeSampleRateLocked(clientId, *it); !result.ok()) { if (auto result = removeContinuousSubscriberLocked(clientId, *it); !result.ok()) { return result; } Loading Loading @@ -244,7 +232,7 @@ VhalResult<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdT auto& subscriptions = mSubscribedPropsByClient[clientId]; for (auto const& propIdAreaId : subscriptions) { if (auto result = removeSampleRateLocked(clientId, propIdAreaId); !result.ok()) { if (auto result = removeContinuousSubscriberLocked(clientId, propIdAreaId); !result.ok()) { return result; } Loading automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +6 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h +9 −9 Original line number Diff line number Diff line Loading @@ -123,10 +123,10 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi std::shared_ptr<PendingRequestPool> mPendingRequestPool; }; // A wrapper for binder operations to enable stubbing for test. class IBinder { // A wrapper for binder lifecycle operations to enable stubbing for test. class BinderLifecycleInterface { public: virtual ~IBinder() = default; virtual ~BinderLifecycleInterface() = default; virtual binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) = 0; Loading @@ -134,8 +134,8 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi virtual bool isAlive(const AIBinder* binder) = 0; }; // A real implementation for IBinder. class AIBinderImpl final : public IBinder { // A real implementation for BinderLifecycleInterface. class BinderLifecycleHandler final : public BinderLifecycleInterface { public: binder_status_t linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) override; Loading @@ -154,7 +154,7 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi // BinderDiedUnlinkedEvent represents either an onBinderDied or an onBinderUnlinked event. struct BinderDiedUnlinkedEvent { // true for onBinderDied, false for onBinderUnlinked. bool onBinderDied; bool forOnBinderDied; const AIBinder* clientId; }; Loading Loading @@ -186,8 +186,8 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi GUARDED_BY(mLock); // SubscriptionClients is thread-safe. std::shared_ptr<SubscriptionClients> mSubscriptionClients; // mBinderImpl is only going to be changed in test. std::unique_ptr<IBinder> mBinderImpl; // mBinderLifecycleHandler is only going to be changed in test. std::unique_ptr<BinderLifecycleInterface> mBinderLifecycleHandler; // Only initialized once. std::shared_ptr<std::function<void()>> mRecurrentAction; Loading Loading @@ -263,7 +263,7 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi void setTimeout(int64_t timeoutInNano); // Test-only void setBinderImpl(std::unique_ptr<IBinder> impl); void setBinderLifecycleHandler(std::unique_ptr<BinderLifecycleInterface> impl); }; } // namespace vehicle Loading
automotive/vehicle/aidl/impl/vhal/include/SubscriptionManager.h +16 −17 Original line number Diff line number Diff line Loading @@ -41,15 +41,15 @@ class ContSubConfigs final { public: using ClientIdType = const AIBinder*; void addClient(const ClientIdType& clientId, float sampleRate); void addClient(const ClientIdType& clientId, float sampleRateHz); void removeClient(const ClientIdType& clientId); float getMaxSampleRate(); float getMaxSampleRateHz() const; private: float mMaxSampleRate = 0.; std::unordered_map<ClientIdType, float> mSampleRates; float mMaxSampleRateHz = 0.; std::unordered_map<ClientIdType, float> mSampleRateHzByClient; void refreshMaxSampleRate(); void refreshMaxSampleRateHz(); }; // A thread-safe subscription manager that manages all VHAL subscriptions. Loading @@ -59,7 +59,7 @@ class SubscriptionManager final { using CallbackType = std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>; explicit SubscriptionManager(IVehicleHardware* hardware); explicit SubscriptionManager(IVehicleHardware* vehicleHardware); ~SubscriptionManager(); // Subscribes to properties according to {@code SubscribeOptions}. Note that all option must Loading Loading @@ -99,13 +99,8 @@ class SubscriptionManager final { const std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>& updatedValues); // Gets the sample rate for the continuous property. Returns {@code std::nullopt} if the // property has not been subscribed before or is not a continuous property. std::optional<float> getSampleRate(const ClientIdType& clientId, int32_t propId, int32_t areaId); // Checks whether the sample rate is valid. static bool checkSampleRate(float sampleRate); static bool checkSampleRateHz(float sampleRateHz); private: // Friend class for testing. Loading @@ -122,17 +117,21 @@ class SubscriptionManager final { std::unordered_map<PropIdAreaId, ContSubConfigs, PropIdAreaIdHash> mContSubConfigsByPropIdArea GUARDED_BY(mLock); VhalResult<void> updateSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRate) VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz) REQUIRES(mLock); VhalResult<void> removeContinuousSubscriberLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) REQUIRES(mLock); VhalResult<void> removeSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) REQUIRES(mLock); VhalResult<void> updateContSubConfigs(const PropIdAreaId& PropIdAreaId, const ContSubConfigs& newConfig) REQUIRES(mLock); // Checks whether the manager is empty. For testing purpose. bool isEmpty(); // Get the interval in nanoseconds accroding to sample rate. static android::base::Result<int64_t> getInterval(float sampleRate); static android::base::Result<int64_t> getIntervalNanos(float sampleRateHz); }; } // namespace vehicle Loading
automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp +51 −48 Original line number Diff line number Diff line Loading @@ -78,14 +78,14 @@ std::string toString(const std::unordered_set<int64_t>& values) { return str; } float getDefaultSampleRate(float sampleRate, float minSampleRate, float maxSampleRate) { if (sampleRate < minSampleRate) { return minSampleRate; float getDefaultSampleRateHz(float sampleRateHz, float minSampleRateHz, float maxSampleRateHz) { if (sampleRateHz < minSampleRateHz) { return minSampleRateHz; } if (sampleRate > maxSampleRate) { return maxSampleRate; if (sampleRateHz > maxSampleRateHz) { return maxSampleRateHz; } return sampleRate; return sampleRateHz; } } // namespace Loading Loading @@ -123,8 +123,8 @@ size_t DefaultVehicleHal::SubscriptionClients::countClients() { return mClients.size(); } DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) : mVehicleHardware(std::move(hardware)), DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware) : mVehicleHardware(std::move(vehicleHardware)), mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) { auto configs = mVehicleHardware->getAllPropertyConfigs(); for (auto& config : configs) { Loading @@ -143,12 +143,11 @@ DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) mConfigFile = std::move(result.value()); } mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool); mSubscriptionClients = std::make_shared<SubscriptionClients>(mPendingRequestPool); auto subscribeIdByClient = std::make_shared<SubscribeIdByClient>(); IVehicleHardware* hardwarePtr = mVehicleHardware.get(); mSubscriptionManager = std::make_shared<SubscriptionManager>(hardwarePtr); IVehicleHardware* vehicleHardwarePtr = mVehicleHardware.get(); mSubscriptionManager = std::make_shared<SubscriptionManager>(vehicleHardwarePtr); std::weak_ptr<SubscriptionManager> subscriptionManagerCopy = mSubscriptionManager; mVehicleHardware->registerOnPropertyChangeEvent( Loading @@ -158,13 +157,13 @@ DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware) })); // Register heartbeat event. mRecurrentAction = std::make_shared<std::function<void()>>([hardwarePtr, subscriptionManagerCopy]() { checkHealth(hardwarePtr, subscriptionManagerCopy); mRecurrentAction = std::make_shared<std::function<void()>>( [vehicleHardwarePtr, subscriptionManagerCopy]() { checkHealth(vehicleHardwarePtr, subscriptionManagerCopy); }); mRecurrentTimer.registerTimerCallback(HEART_BEAT_INTERVAL_IN_NANO, mRecurrentAction); mBinderImpl = std::make_unique<AIBinderImpl>(); mBinderLifecycleHandler = std::make_unique<BinderLifecycleHandler>(); mOnBinderDiedUnlinkedHandlerThread = std::thread([this] { onBinderDiedUnlinkedHandler(); }); mDeathRecipient = ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(&DefaultVehicleHal::onBinderDied)); Loading Loading @@ -220,7 +219,7 @@ std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient( bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) { OnBinderDiedContext* contextPtr = nullptr; if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) { return mBinderImpl->isAlive(clientId); return mBinderLifecycleHandler->isAlive(clientId); } else { std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>( OnBinderDiedContext{.vhal = this, .clientId = clientId}); Loading @@ -232,7 +231,7 @@ bool DefaultVehicleHal::monitorBinderLifeCycleLocked(const AIBinder* clientId) { } // If this function fails, onBinderUnlinked would be called to remove the added context. binder_status_t status = mBinderImpl->linkToDeath( binder_status_t status = mBinderLifecycleHandler->linkToDeath( const_cast<AIBinder*>(clientId), mDeathRecipient.get(), static_cast<void*>(contextPtr)); if (status == STATUS_OK) { return true; Loading @@ -246,7 +245,8 @@ void DefaultVehicleHal::onBinderDied(void* cookie) { OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie); // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same // thread because we might be holding the mLock the handler requires. context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{true, context->clientId}); context->vhal->mBinderEvents.push( BinderDiedUnlinkedEvent{/*forOnBinderDied=*/true, context->clientId}); } void DefaultVehicleHal::onBinderDiedWithContext(const AIBinder* clientId) { Loading @@ -262,7 +262,8 @@ void DefaultVehicleHal::onBinderUnlinked(void* cookie) { OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie); // To be handled in mOnBinderDiedUnlinkedHandlerThread. We cannot handle the event in the same // thread because we might be holding the mLock the handler requires. context->vhal->mBinderEvents.push(BinderDiedUnlinkedEvent{false, context->clientId}); context->vhal->mBinderEvents.push( BinderDiedUnlinkedEvent{/*forOnBinderDied=*/false, context->clientId}); } void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) { Loading @@ -275,7 +276,7 @@ void DefaultVehicleHal::onBinderUnlinkedWithContext(const AIBinder* clientId) { void DefaultVehicleHal::onBinderDiedUnlinkedHandler() { while (mBinderEvents.waitForItems()) { for (BinderDiedUnlinkedEvent& event : mBinderEvents.flush()) { if (event.onBinderDied) { if (event.forOnBinderDied) { onBinderDiedWithContext(event.clientId); } else { onBinderUnlinkedWithContext(event.clientId); Loading Loading @@ -349,15 +350,15 @@ Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback, const GetValueRequests& requests) { if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } expected<LargeParcelableBase::BorrowedOwnedObject<GetValueRequests>, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests); if (!deserializedResults.ok()) { ALOGE("getValues: failed to parse getValues requests"); return std::move(deserializedResults.error()); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } const std::vector<GetValueRequest>& getValueRequests = deserializedResults.value().getObject()->payloads; Loading Loading @@ -435,15 +436,15 @@ ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback, ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback, const SetValueRequests& requests) { if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } expected<LargeParcelableBase::BorrowedOwnedObject<SetValueRequests>, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests); if (!deserializedResults.ok()) { ALOGE("setValues: failed to parse setValues requests"); return std::move(deserializedResults.error()); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } const std::vector<SetValueRequest>& setValueRequests = deserializedResults.value().getObject()->payloads; Loading Loading @@ -595,18 +596,20 @@ VhalResult<void> DefaultVehicleHal::checkSubscribeOptions( } if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { float sampleRate = option.sampleRate; float minSampleRate = config.minSampleRate; float maxSampleRate = config.maxSampleRate; if (sampleRate < minSampleRate || sampleRate > maxSampleRate) { float defaultRate = getDefaultSampleRate(sampleRate, minSampleRate, maxSampleRate); ALOGW("sample rate: %f out of range, must be within %f and %f, set to %f", sampleRate, minSampleRate, maxSampleRate, defaultRate); sampleRate = defaultRate; } if (!SubscriptionManager::checkSampleRate(sampleRate)) { float sampleRateHz = option.sampleRate; float minSampleRateHz = config.minSampleRate; float maxSampleRateHz = config.maxSampleRate; float defaultRateHz = getDefaultSampleRateHz(sampleRateHz, minSampleRateHz, maxSampleRateHz); if (sampleRateHz != defaultRateHz) { ALOGW("sample rate: %f HZ out of range, must be within %f HZ and %f HZ , set to %f " "HZ", sampleRateHz, minSampleRateHz, maxSampleRateHz, defaultRateHz); sampleRateHz = defaultRateHz; } if (!SubscriptionManager::checkSampleRateHz(sampleRateHz)) { return StatusError(StatusCode::INVALID_ARG) << "invalid sample rate: " << sampleRate; << "invalid sample rate: " << sampleRateHz << " HZ"; } } Loading @@ -631,13 +634,13 @@ ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, const std::vector<SubscribeOptions>& options, [[maybe_unused]] int32_t maxSharedMemoryFileCount) { // TODO(b/205189110): Use shared memory file count. if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } if (auto result = checkSubscribeOptions(options); !result.ok()) { ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str()); return toScopedAStatus(result); } if (callback == nullptr) { return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER); } std::vector<SubscribeOptions> onChangeSubscriptions; std::vector<SubscribeOptions> continuousSubscriptions; for (const auto& option : options) { Loading @@ -658,7 +661,7 @@ ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback, } if (config.changeMode == VehiclePropertyChangeMode::CONTINUOUS) { optionCopy.sampleRate = getDefaultSampleRate( optionCopy.sampleRate = getDefaultSampleRateHz( optionCopy.sampleRate, config.minSampleRate, config.maxSampleRate); continuousSubscriptions.push_back(std::move(optionCopy)); } else { Loading Loading @@ -740,9 +743,9 @@ VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& return {}; } void DefaultVehicleHal::checkHealth(IVehicleHardware* hardware, void DefaultVehicleHal::checkHealth(IVehicleHardware* vehicleHardware, std::weak_ptr<SubscriptionManager> subscriptionManager) { StatusCode status = hardware->checkHealth(); StatusCode status = vehicleHardware->checkHealth(); if (status != StatusCode::OK) { ALOGE("VHAL check health returns non-okay status"); return; Loading @@ -757,18 +760,18 @@ void DefaultVehicleHal::checkHealth(IVehicleHardware* hardware, return; } binder_status_t DefaultVehicleHal::AIBinderImpl::linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { binder_status_t DefaultVehicleHal::BinderLifecycleHandler::linkToDeath( AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) { return AIBinder_linkToDeath(binder, recipient, cookie); } bool DefaultVehicleHal::AIBinderImpl::isAlive(const AIBinder* binder) { bool DefaultVehicleHal::BinderLifecycleHandler::isAlive(const AIBinder* binder) { return AIBinder_isAlive(binder); } void DefaultVehicleHal::setBinderImpl(std::unique_ptr<IBinder> impl) { mBinderImpl = std::move(impl); void DefaultVehicleHal::setBinderLifecycleHandler( std::unique_ptr<BinderLifecycleInterface> handler) { mBinderLifecycleHandler = std::move(handler); } bool DefaultVehicleHal::checkDumpPermission() { Loading
automotive/vehicle/aidl/impl/vhal/src/SubscriptionManager.cpp +53 −65 Original line number Diff line number Diff line Loading @@ -42,7 +42,8 @@ using ::android::base::Result; using ::android::base::StringPrintf; using ::ndk::ScopedAStatus; SubscriptionManager::SubscriptionManager(IVehicleHardware* hardware) : mVehicleHardware(hardware) {} SubscriptionManager::SubscriptionManager(IVehicleHardware* vehicleHardware) : mVehicleHardware(vehicleHardware) {} SubscriptionManager::~SubscriptionManager() { std::scoped_lock<std::mutex> lockGuard(mLock); Loading @@ -51,94 +52,82 @@ SubscriptionManager::~SubscriptionManager() { mSubscribedPropsByClient.clear(); } bool SubscriptionManager::checkSampleRate(float sampleRate) { return getInterval(sampleRate).ok(); bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) { return getIntervalNanos(sampleRateHz).ok(); } Result<int64_t> SubscriptionManager::getInterval(float sampleRate) { int64_t interval = 0; if (sampleRate <= 0) { Result<int64_t> SubscriptionManager::getIntervalNanos(float sampleRateHz) { int64_t intervalNanos = 0; if (sampleRateHz <= 0) { return Error() << "invalid sample rate, must be a positive number"; } if (sampleRate <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) { return Error() << "invalid sample rate: " << sampleRate << ", too small"; if (sampleRateHz <= (ONE_SECOND_IN_NANO / static_cast<float>(INT64_MAX))) { return Error() << "invalid sample rate: " << sampleRateHz << ", too small"; } interval = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRate); return interval; intervalNanos = static_cast<int64_t>(ONE_SECOND_IN_NANO / sampleRateHz); return intervalNanos; } void ContSubConfigs::refreshMaxSampleRate() { float maxSampleRate = 0.; void ContSubConfigs::refreshMaxSampleRateHz() { float maxSampleRateHz = 0.; // This is not called frequently so a brute-focre is okay. More efficient way exists but this // is simpler. for (const auto& [_, sampleRate] : mSampleRates) { if (sampleRate > maxSampleRate) { maxSampleRate = sampleRate; for (const auto& [_, sampleRateHz] : mSampleRateHzByClient) { if (sampleRateHz > maxSampleRateHz) { maxSampleRateHz = sampleRateHz; } } mMaxSampleRate = maxSampleRate; mMaxSampleRateHz = maxSampleRateHz; } void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRate) { mSampleRates[clientId] = sampleRate; refreshMaxSampleRate(); void ContSubConfigs::addClient(const ClientIdType& clientId, float sampleRateHz) { mSampleRateHzByClient[clientId] = sampleRateHz; refreshMaxSampleRateHz(); } void ContSubConfigs::removeClient(const ClientIdType& clientId) { mSampleRates.erase(clientId); refreshMaxSampleRate(); mSampleRateHzByClient.erase(clientId); refreshMaxSampleRateHz(); } float ContSubConfigs::getMaxSampleRate() { return mMaxSampleRate; float ContSubConfigs::getMaxSampleRateHz() const { return mMaxSampleRateHz; } VhalResult<void> SubscriptionManager::updateSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRate) { VhalResult<void> SubscriptionManager::addContinuousSubscriberLocked( const ClientIdType& clientId, const PropIdAreaId& propIdAreaId, float sampleRateHz) { // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId]; infoCopy.addClient(clientId, sampleRate); if (infoCopy.getMaxSampleRate() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) { mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; return {}; } float newRate = infoCopy.getMaxSampleRate(); int32_t propId = propIdAreaId.propId; int32_t areaId = propIdAreaId.areaId; if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate); status != StatusCode::OK) { return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32 ", area" ": %" PRId32 ", sample rate: %f", propId, areaId, newRate); } mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; return {}; ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; newConfig.addClient(clientId, sampleRateHz); return updateContSubConfigs(propIdAreaId, newConfig); } VhalResult<void> SubscriptionManager::removeSampleRateLocked(const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) { VhalResult<void> SubscriptionManager::removeContinuousSubscriberLocked( const ClientIdType& clientId, const PropIdAreaId& propIdAreaId) { // Make a copy so that we don't modify 'mContSubConfigsByPropIdArea' on failure cases. ContSubConfigs infoCopy = mContSubConfigsByPropIdArea[propIdAreaId]; infoCopy.removeClient(clientId); if (infoCopy.getMaxSampleRate() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRate()) { mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; ContSubConfigs newConfig = mContSubConfigsByPropIdArea[propIdAreaId]; newConfig.removeClient(clientId); return updateContSubConfigs(propIdAreaId, newConfig); } VhalResult<void> SubscriptionManager::updateContSubConfigs(const PropIdAreaId& propIdAreaId, const ContSubConfigs& newConfig) { if (newConfig.getMaxSampleRateHz() == mContSubConfigsByPropIdArea[propIdAreaId].getMaxSampleRateHz()) { mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; return {}; } float newRate = infoCopy.getMaxSampleRate(); float newRateHz = newConfig.getMaxSampleRateHz(); int32_t propId = propIdAreaId.propId; int32_t areaId = propIdAreaId.areaId; if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRate); if (auto status = mVehicleHardware->updateSampleRate(propId, areaId, newRateHz); status != StatusCode::OK) { return StatusError(status) << StringPrintf("failed to update sample rate for prop: %" PRId32 ", area" ": %" PRId32 ", sample rate: %f", propId, areaId, newRate); ": %" PRId32 ", sample rate: %f HZ", propId, areaId, newRateHz); } mContSubConfigsByPropIdArea[propIdAreaId] = infoCopy; mContSubConfigsByPropIdArea[propIdAreaId] = newConfig; return {}; } Loading @@ -147,14 +136,12 @@ VhalResult<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCa bool isContinuousProperty) { std::scoped_lock<std::mutex> lockGuard(mLock); std::vector<int64_t> intervals; for (const auto& option : options) { float sampleRate = option.sampleRate; float sampleRateHz = option.sampleRate; if (isContinuousProperty) { auto intervalResult = getInterval(sampleRate); if (!intervalResult.ok()) { return StatusError(StatusCode::INVALID_ARG) << intervalResult.error().message(); if (auto result = getIntervalNanos(sampleRateHz); !result.ok()) { return StatusError(StatusCode::INVALID_ARG) << result.error().message(); } } Loading @@ -176,7 +163,8 @@ VhalResult<void> SubscriptionManager::subscribe(const std::shared_ptr<IVehicleCa .areaId = areaId, }; if (isContinuousProperty) { if (auto result = updateSampleRateLocked(clientId, propIdAreaId, option.sampleRate); if (auto result = addContinuousSubscriberLocked(clientId, propIdAreaId, option.sampleRate); !result.ok()) { return result; } Loading Loading @@ -214,7 +202,7 @@ VhalResult<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdT while (it != propIdAreaIds.end()) { int32_t propId = it->propId; if (std::find(propIds.begin(), propIds.end(), propId) != propIds.end()) { if (auto result = removeSampleRateLocked(clientId, *it); !result.ok()) { if (auto result = removeContinuousSubscriberLocked(clientId, *it); !result.ok()) { return result; } Loading Loading @@ -244,7 +232,7 @@ VhalResult<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdT auto& subscriptions = mSubscribedPropsByClient[clientId]; for (auto const& propIdAreaId : subscriptions) { if (auto result = removeSampleRateLocked(clientId, propIdAreaId); !result.ok()) { if (auto result = removeContinuousSubscriberLocked(clientId, propIdAreaId); !result.ok()) { return result; } Loading
automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +6 −6 File changed.Preview size limit exceeded, changes collapsed. Show changes