/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "VehiclePropertyStore" #include <log/log.h> #include <common/include/vhal_v2_0/VehicleUtils.h> #include "VehiclePropertyStore.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const { return prop == other.prop && area == other.area && token == other.token; } bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const { return prop < other.prop || (prop == other.prop && area < other.area) || (prop == other.prop && area == other.area && token < other.token); } void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config, VehiclePropertyStore::TokenFunction tokenFunc) { MuxGuard g(mLock); mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } }); } bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) { MuxGuard g(mLock); if (!mConfigs.count(propValue.prop)) return false; RecordId recId = getRecordIdLocked(propValue); VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId)); if (valueToUpdate == nullptr) { mPropertyValues.insert({ recId, propValue }); } else { valueToUpdate->timestamp = propValue.timestamp; valueToUpdate->value = propValue.value; } return true; } void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) { MuxGuard g(mLock); RecordId recId = getRecordIdLocked(propValue); auto it = mPropertyValues.find(recId); if (it != mPropertyValues.end()) { mPropertyValues.erase(it); } } void VehiclePropertyStore::removeValuesForProperty(int32_t propId) { MuxGuard g(mLock); auto range = findRangeLocked(propId); mPropertyValues.erase(range.first, range.second); } std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const { MuxGuard g(mLock); std::vector<VehiclePropValue> allValues; allValues.reserve(mPropertyValues.size()); for (auto&& it : mPropertyValues) { allValues.push_back(it.second); } return allValues; } std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const { std::vector<VehiclePropValue> values; MuxGuard g(mLock); auto range = findRangeLocked(propId); for (auto it = range.first; it != range.second; ++it) { values.push_back(it->second); } return values; } std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull( const VehiclePropValue& request) const { MuxGuard g(mLock); RecordId recId = getRecordIdLocked(request); const VehiclePropValue* internalValue = getValueOrNullLocked(recId); return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr; } std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull( int32_t prop, int32_t area, int64_t token) const { RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token }; MuxGuard g(mLock); const VehiclePropValue* internalValue = getValueOrNullLocked(recId); return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr; } std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const { MuxGuard g(mLock); std::vector<VehiclePropConfig> configs; configs.reserve(mConfigs.size()); for (auto&& recordConfigIt: mConfigs) { configs.push_back(recordConfigIt.second.propConfig); } return configs; } const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const { MuxGuard g(mLock); auto recordConfigIt = mConfigs.find(propId); return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr; } const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const { auto cfg = getConfigOrNull(propId); if (!cfg) { ALOGW("%s: config not found for property: 0x%x", __func__, propId); abort(); } return cfg; } VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked( const VehiclePropValue& valuePrototype) const { RecordId recId = { .prop = valuePrototype.prop, .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId, .token = 0 }; auto it = mConfigs.find(recId.prop); if (it == mConfigs.end()) return {}; if (it->second.tokenFunction != nullptr) { recId.token = it->second.tokenFunction(valuePrototype); } return recId; } const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked( const VehiclePropertyStore::RecordId& recId) const { auto it = mPropertyValues.find(recId); return it == mPropertyValues.end() ? nullptr : &it->second; } VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const { // Based on the fact that mPropertyValues is a sorted map by RecordId. auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 }); auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 }); return PropertyMapRange { beginIt, endIt }; } } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android