Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b45694b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve reference VHAL library."

parents eb1b8a4e 6f543488
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
    };

@@ -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;
@@ -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
+16 −17
Original line number Diff line number Diff line
@@ -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.
@@ -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
@@ -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.
@@ -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
+51 −48
Original line number Diff line number Diff line
@@ -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
@@ -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) {
@@ -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(
@@ -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));
@@ -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});
@@ -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;
@@ -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) {
@@ -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) {
@@ -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);
@@ -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;

@@ -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;

@@ -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";
            }
        }

@@ -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) {
@@ -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 {
@@ -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;
@@ -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() {
+53 −65
Original line number Diff line number Diff line
@@ -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);
@@ -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 {};
}

@@ -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();
            }
        }

@@ -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;
                }
@@ -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;
            }

@@ -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;
        }

+6 −6

File changed.

Preview size limit exceeded, changes collapsed.

Loading