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

Commit 4906afbf authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I61e086b4,I29fc11a0 into main

* changes:
  Fix invalid memory access in DefaultVehicleHal.
  Implement reg/unregSupportedValueChange.
parents e4979f49 26410152
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -303,6 +303,8 @@ class IVehicleHardware {
    //
    // If the propertyId's supported values are static, then must do nothing.
    //
    // If some of the [propId, areaId]s are already subscribed, then do nothing.
    //
    // This is only called for [propId, areaId] that has non-null {@code HasSupportedValueInfo}.
    //
    // Client must implement (override) this function if at least one [propId, areaId]'s
+2 −2
Original line number Diff line number Diff line
@@ -233,9 +233,9 @@ class DefaultVehicleHal final : public aidlvhal::BnVehicle {
            std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
                    callback) const EXCLUDES(mConfigLock);

    android::base::Result<const aidlvhal::VehicleAreaConfig*> getAreaConfigForPropIdAreaId(
    android::base::Result<aidlvhal::VehicleAreaConfig> getAreaConfigForPropIdAreaId(
            int32_t propId, int32_t areaId) const;
    android::base::Result<const aidlvhal::HasSupportedValueInfo*> getHasSupportedValueInfo(
    android::base::Result<aidlvhal::HasSupportedValueInfo> getHasSupportedValueInfo(
            int32_t propId, int32_t areaId) const;
    // Puts the property change events into a queue so that they can handled in batch.
    static void batchPropertyChangeEvent(
+21 −2
Original line number Diff line number Diff line
@@ -118,8 +118,19 @@ class SubscriptionManager final {
                       std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropError>>
    getSubscribedClientsForErrorEvents(const std::vector<SetValueErrorEvent>& errorEvents);

    // Returns the number of subscribed clients.
    size_t countClients();
    // Subscribes to supported values change.
    VhalResult<void> subscribeSupportedValueChange(const CallbackType& callback,
                                                   const std::vector<PropIdAreaId>& propIdAreaIds);

    // Unsubscribes to supported values change.
    VhalResult<void> unsubscribeSupportedValueChange(
            ClientIdType client, const std::vector<PropIdAreaId>& propIdAreaIds);

    // Returns the number of subscribed property change clients.
    size_t countPropertyChangeClients();

    // Returns the number of subscribed supported value change clients.
    size_t countSupportedValueChangeClients();

    // Checks whether the sample rate is valid.
    static bool checkSampleRateHz(float sampleRateHz);
@@ -160,6 +171,11 @@ class SubscriptionManager final {
                       std::unordered_set<VehiclePropValue, VehiclePropValueHashPropIdAreaId,
                                          VehiclePropValueEqualPropIdAreaId>>
            mContSubValuesByCallback GUARDED_BY(mLock);
    std::unordered_map<PropIdAreaId, std::unordered_map<ClientIdType, CallbackType>,
                       PropIdAreaIdHash>
            mSupportedValueChangeClientsByPropIdAreaId GUARDED_BY(mLock);
    std::unordered_map<ClientIdType, std::unordered_set<PropIdAreaId, PropIdAreaIdHash>>
            mSupportedValueChangePropIdAreaIdsByClient GUARDED_BY(mLock);

    VhalResult<void> addContinuousSubscriberLocked(const ClientIdType& clientId,
                                                   const PropIdAreaId& propIdAreaId,
@@ -180,6 +196,9 @@ class SubscriptionManager final {
    VhalResult<void> unsubscribePropIdAreaIdLocked(SubscriptionManager::ClientIdType clientId,
                                                   const PropIdAreaId& propIdAreaId)
            REQUIRES(mLock);
    VhalResult<void> unsubscribeSupportedValueChangeLocked(
            SubscriptionManager::ClientIdType clientId,
            const std::vector<PropIdAreaId>& propIdAreaIds) REQUIRES(mLock);

    // Checks whether the manager is empty. For testing purpose.
    bool isEmpty();
+72 −23
Original line number Diff line number Diff line
@@ -82,9 +82,6 @@ using ::ndk::ScopedFileDescriptor;

using VhalPropIdAreaId = ::aidl::android::hardware::automotive::vehicle::PropIdAreaId;

#define propIdtoString(PROP_ID) \
    aidl::android::hardware::automotive::vehicle::toString(static_cast<VehicleProperty>(PROP_ID))

std::string toString(const std::unordered_set<int64_t>& values) {
    std::string str = "";
    for (auto it = values.begin(); it != values.end(); it++) {
@@ -972,25 +969,25 @@ ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t
    return ScopedAStatus::ok();
}

Result<const VehicleAreaConfig*> DefaultVehicleHal::getAreaConfigForPropIdAreaId(
        int32_t propId, int32_t areaId) const {
Result<VehicleAreaConfig> DefaultVehicleHal::getAreaConfigForPropIdAreaId(int32_t propId,
                                                                          int32_t areaId) const {
    auto result = getConfig(propId);
    if (!result.ok()) {
        return Error() << "Failed to get property config for propertyId: " << propIdtoString(propId)
        return Error() << "Failed to get property config for propertyId: " << propIdToString(propId)
                       << ", error: " << result.error();
    }
    const VehiclePropConfig& config = result.value();
    const VehicleAreaConfig* areaConfig = getAreaConfig(propId, areaId, config);
    if (areaConfig == nullptr) {
        return Error() << "AreaId config not found for propertyId: " << propIdtoString(propId)
        return Error() << "AreaId config not found for propertyId: " << propIdToString(propId)
                       << ", areaId: " << areaId;
    }
    return areaConfig;
    return *areaConfig;
}

Result<const HasSupportedValueInfo*> DefaultVehicleHal::getHasSupportedValueInfo(
        int32_t propId, int32_t areaId) const {
    Result<const VehicleAreaConfig*> propIdAreaIdConfigResult =
Result<HasSupportedValueInfo> DefaultVehicleHal::getHasSupportedValueInfo(int32_t propId,
                                                                          int32_t areaId) const {
    Result<VehicleAreaConfig> propIdAreaIdConfigResult =
            getAreaConfigForPropIdAreaId(propId, areaId);
    if (!isGlobalProp(propId) && !propIdAreaIdConfigResult.ok()) {
        // For global property, it is possible that no config exists.
@@ -998,11 +995,11 @@ Result<const HasSupportedValueInfo*> DefaultVehicleHal::getHasSupportedValueInfo
    }
    if (propIdAreaIdConfigResult.has_value()) {
        auto areaConfig = propIdAreaIdConfigResult.value();
        if (areaConfig->hasSupportedValueInfo.has_value()) {
            return &(areaConfig->hasSupportedValueInfo.value());
        if (areaConfig.hasSupportedValueInfo.has_value()) {
            return areaConfig.hasSupportedValueInfo.value();
        }
    }
    return Error() << "property: " << propIdtoString(propId) << ", areaId: " << areaId
    return Error() << "property: " << propIdToString(propId) << ", areaId: " << areaId
                   << " does not support this operation because hasSupportedValueInfo is null";
}

@@ -1026,7 +1023,7 @@ ScopedAStatus DefaultVehicleHal::getSupportedValuesLists(
            continue;
        }

        const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
        const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
        if (hasSupportedValueInfo.hasSupportedValuesList) {
            toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
            toHardwareRequestCounters.push_back(requestCounter);
@@ -1087,7 +1084,7 @@ ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
            continue;
        }

        const auto& hasSupportedValueInfo = *(hasSupportedValueInfoResult.value());
        const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
        if (hasSupportedValueInfo.hasMinSupportedValue ||
            hasSupportedValueInfo.hasMaxSupportedValue) {
            toHardwarePropIdAreaIds.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
@@ -1130,15 +1127,65 @@ ScopedAStatus DefaultVehicleHal::getMinMaxSupportedValue(
}

ScopedAStatus DefaultVehicleHal::registerSupportedValueChangeCallback(
        const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
    // TODO(b/381020465): Add relevant implementation.
    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
        const std::shared_ptr<IVehicleCallback>& callback,
        const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
    std::vector<PropIdAreaId> propIdAreaIdsToSubscribe;
    for (size_t i = 0; i < vhalPropIdAreaIds.size(); i++) {
        const auto& vhalPropIdAreaId = vhalPropIdAreaIds.at(i);
        int32_t propId = vhalPropIdAreaId.propId;
        int32_t areaId = vhalPropIdAreaId.areaId;
        auto hasSupportedValueInfoResult = getHasSupportedValueInfo(propId, areaId);
        if (!hasSupportedValueInfoResult.ok()) {
            ALOGE("registerSupportedValueChangeCallback not supported: %s",
                  hasSupportedValueInfoResult.error().message().c_str());
            return toScopedAStatus(hasSupportedValueInfoResult, StatusCode::INVALID_ARG);
        }
        const auto& hasSupportedValueInfo = hasSupportedValueInfoResult.value();
        if (!hasSupportedValueInfo.hasMinSupportedValue &&
            !hasSupportedValueInfo.hasMaxSupportedValue &&
            !hasSupportedValueInfo.hasSupportedValuesList) {
            ALOGW("registerSupportedValueChangeCallback: do nothing for property: %s, "
                  "areaId: %" PRId32
                  ", no min/max supported values or supported values list"
                  " specified",
                  propIdToString(propId).c_str(), areaId);
            continue;
        }
        propIdAreaIdsToSubscribe.push_back(PropIdAreaId{.propId = propId, .areaId = areaId});
    }
    if (propIdAreaIdsToSubscribe.empty()) {
        return ScopedAStatus::ok();
    }
    auto result =
            mSubscriptionManager->subscribeSupportedValueChange(callback, propIdAreaIdsToSubscribe);
    if (!result.ok()) {
        ALOGW("registerSupportedValueChangeCallback: failed to subscribe supported value change"
              " for %s, error: %s",
              fmt::format("{}", propIdAreaIdsToSubscribe).c_str(),
              result.error().message().c_str());
        return toScopedAStatus(result);
    }
    return ScopedAStatus::ok();
}

ScopedAStatus DefaultVehicleHal::unregisterSupportedValueChangeCallback(
        const std::shared_ptr<IVehicleCallback>&, const std::vector<VhalPropIdAreaId>&) {
    // TODO(b/381020465): Add relevant implementation.
    return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
        const std::shared_ptr<IVehicleCallback>& callback,
        const std::vector<VhalPropIdAreaId>& vhalPropIdAreaIds) {
    std::vector<PropIdAreaId> propIdAreaIds;
    for (const auto& vhalPropIdAreaId : vhalPropIdAreaIds) {
        propIdAreaIds.push_back(
                PropIdAreaId{.propId = vhalPropIdAreaId.propId, .areaId = vhalPropIdAreaId.areaId});
    }

    auto result = mSubscriptionManager->unsubscribeSupportedValueChange(callback->asBinder().get(),
                                                                        propIdAreaIds);
    if (!result.ok()) {
        ALOGW("unregisterSupportedValueChangeCallback: failed to unsubscribe supported value change"
              " for %s, error: %s",
              fmt::format("{}", propIdAreaIds).c_str(), result.error().message().c_str());
        return toScopedAStatus(result);
    }
    return ScopedAStatus::ok();
}

IVehicleHardware* DefaultVehicleHal::getHardware() {
@@ -1256,12 +1303,14 @@ binder_status_t DefaultVehicleHal::dump(int fd, const char** args, uint32_t numA
        dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
        dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
        dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
        dprintf(fd, "Currently have %zu supported values change subscribe clients\n",
                mSubscriptionManager->countSupportedValueChangeClients());
    }
    return STATUS_OK;
}

size_t DefaultVehicleHal::countSubscribeClients() {
    return mSubscriptionManager->countClients();
    return mSubscriptionManager->countPropertyChangeClients();
}

}  // namespace vehicle
+113 −9
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "SubscriptionManager.h"

#include <VehicleUtils.h>
#include <android-base/format.h>
#include <android-base/stringprintf.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -65,6 +66,8 @@ SubscriptionManager::~SubscriptionManager() {

    mClientsByPropIdAreaId.clear();
    mSubscribedPropsByClient.clear();
    mSupportedValueChangeClientsByPropIdAreaId.clear();
    mSupportedValueChangePropIdAreaIdsByClient.clear();
}

bool SubscriptionManager::checkSampleRateHz(float sampleRateHz) {
@@ -166,8 +169,7 @@ VhalResult<void> SubscriptionManager::addOnChangeSubscriberLocked(
                                    /*enableVur*/ false));
        status != StatusCode::OK) {
        return StatusError(status)
               << StringPrintf("failed subscribe for prop: %s, areaId: %" PRId32,
                               propIdToString(propId).c_str(), areaId);
               << fmt::format("failed subscribe for propIdAreaId: {}", propIdAreaId);
    }
    return {};
}
@@ -379,16 +381,111 @@ VhalResult<void> SubscriptionManager::unsubscribe(SubscriptionManager::ClientIdT

    if (mSubscribedPropsByClient.find(clientId) == mSubscribedPropsByClient.end()) {
        ALOGW("No property was subscribed for this client, unsubscribe does nothing");
        return {};
    }

    auto& subscriptions = mSubscribedPropsByClient[clientId];
    for (auto const& propIdAreaId : subscriptions) {
    } else {
        auto& propIdAreaIds = mSubscribedPropsByClient[clientId];
        for (auto const& propIdAreaId : propIdAreaIds) {
            if (auto result = unsubscribePropIdAreaIdLocked(clientId, propIdAreaId); !result.ok()) {
                return result;
            }
        }
        mSubscribedPropsByClient.erase(clientId);
    }

    if (mSupportedValueChangePropIdAreaIdsByClient.find(clientId) ==
        mSupportedValueChangePropIdAreaIdsByClient.end()) {
        ALOGW("No supported value change was subscribed for this client, unsubscribe does nothing");
    } else {
        const auto& propIdAreaIds = mSupportedValueChangePropIdAreaIdsByClient[clientId];
        if (auto result = unsubscribeSupportedValueChangeLocked(
                    clientId,
                    std::vector<PropIdAreaId>(propIdAreaIds.begin(), propIdAreaIds.end()));
            !result.ok()) {
            return result;
        }
    }
    return {};
}

VhalResult<void> SubscriptionManager::subscribeSupportedValueChange(
        const std::shared_ptr<IVehicleCallback>& callback,
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    // Need to make sure this whole operation is guarded by a lock so that our internal state is
    // consistent with IVehicleHardware state.
    std::scoped_lock<std::mutex> lockGuard(mLock);

    ClientIdType clientId = callback->asBinder().get();

    // It is possible that some of the [propId, areaId]s are already subscribed, IVehicleHardware
    // will ignore them.
    if (auto status = mVehicleHardware->subscribeSupportedValueChange(propIdAreaIds);
        status != StatusCode::OK) {
        return StatusError(status)
               << fmt::format("failed to call subscribeSupportedValueChange for propIdAreaIds: {}",
                              propIdAreaIds);
    }
    for (const auto& propIdAreaId : propIdAreaIds) {
        mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId][clientId] = callback;
        // mSupportedValueChangePropIdAreaIdsByClient[clientId] is a set so this will ignore
        // duplicate [propId, areaId].
        mSupportedValueChangePropIdAreaIdsByClient[clientId].insert(propIdAreaId);
    }
    return {};
}

VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChange(
        SubscriptionManager::ClientIdType clientId,
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    // Need to make sure this whole operation is guarded by a lock so that our internal state is
    // consistent with IVehicleHardware state.
    std::scoped_lock<std::mutex> lockGuard(mLock);

    return unsubscribeSupportedValueChangeLocked(clientId, propIdAreaIds);
}

VhalResult<void> SubscriptionManager::unsubscribeSupportedValueChangeLocked(
        SubscriptionManager::ClientIdType clientId,
        const std::vector<PropIdAreaId>& propIdAreaIds) {
    std::vector<PropIdAreaId> propIdAreaIdsToUnsubscribe;

    // Check which [propId, areaId] needs to be unsubscribed from the hardware.
    for (const auto& propIdAreaId : propIdAreaIds) {
        auto it = mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId);
        if (it != mSupportedValueChangeClientsByPropIdAreaId.end()) {
            const auto& clients = it->second;
            if (clients.size() == 1 && clients.find(clientId) != clients.end()) {
                // This callback is the only client registered for [propId, areaId].
                // Unregister it should unregister the [propId, areaId].
                propIdAreaIdsToUnsubscribe.push_back(propIdAreaId);
            }
        }
    }

    // Send the unsubscribe request.
    if (!propIdAreaIdsToUnsubscribe.empty()) {
        if (auto status =
                    mVehicleHardware->unsubscribeSupportedValueChange(propIdAreaIdsToUnsubscribe);
            status != StatusCode::OK) {
            return StatusError(status) << fmt::format(
                           "failed to call unsubscribeSupportedValueChange for "
                           "propIdAreaIds: {}",
                           propIdAreaIdsToUnsubscribe);
        }
    }

    // Remove internal book-keeping.
    for (const auto& propIdAreaId : propIdAreaIds) {
        if (mSupportedValueChangeClientsByPropIdAreaId.find(propIdAreaId) !=
            mSupportedValueChangeClientsByPropIdAreaId.end()) {
            mSupportedValueChangeClientsByPropIdAreaId[propIdAreaId].erase(clientId);
        }
        if (mSupportedValueChangeClientsByPropIdAreaId.empty()) {
            mSupportedValueChangeClientsByPropIdAreaId.erase(propIdAreaId);
        }
        mSupportedValueChangePropIdAreaIdsByClient[clientId].erase(propIdAreaId);
        if (mSupportedValueChangePropIdAreaIdsByClient[clientId].empty()) {
            mSupportedValueChangePropIdAreaIdsByClient.erase(clientId);
        }
    }
    return {};
}

@@ -486,14 +583,21 @@ SubscriptionManager::getSubscribedClientsForErrorEvents(

bool SubscriptionManager::isEmpty() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty();
    return mSubscribedPropsByClient.empty() && mClientsByPropIdAreaId.empty() &&
           mSupportedValueChangeClientsByPropIdAreaId.empty() &&
           mSupportedValueChangePropIdAreaIdsByClient.empty();
}

size_t SubscriptionManager::countClients() {
size_t SubscriptionManager::countPropertyChangeClients() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mSubscribedPropsByClient.size();
}

size_t SubscriptionManager::countSupportedValueChangeClients() {
    std::scoped_lock<std::mutex> lockGuard(mLock);
    return mSupportedValueChangePropIdAreaIdsByClient.size();
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
Loading