blob: 2812c3b843a86cf1573a125700eed09274d76677 [file] [log] [blame]
/*
* Copyright (C) 2021 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.
*/
#ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <VehicleHalTypes.h>
#include <VehicleObjectPool.h>
#include <VehicleUtils.h>
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {
// Encapsulates work related to storing and accessing configuration, storing and modifying
// vehicle property values.
//
// VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
// to get value for all areas for particular property.
//
// This class is thread-safe, however it uses blocking synchronization across all methods.
class VehiclePropertyStore final {
public:
using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
using ValuesResultType = VhalResult<std::vector<VehiclePropValuePool::RecyclableType>>;
enum class EventMode : uint8_t {
/**
* Only invoke OnValueChangeCallback if the new property value (ignoring timestamp) is
* different than the existing value.
*
* This should be used for regular cases.
*/
ON_VALUE_CHANGE,
/**
* Always invoke OnValueChangeCallback.
*
* This should be used for the special properties that are used for delivering event, e.g.
* HW_KEY_INPUT.
*/
ALWAYS,
/**
* Never invoke OnValueChangeCallback.
*
* This should be used for continuous property subscription when the sample rate for the
* subscription is smaller than the refresh rate for the property. E.g., the vehicle speed
* is refreshed at 20hz, but we are only subscribing at 10hz. In this case, we want to
* generate the property change event at 10hz, not 20hz, but we still want to refresh the
* timestamp (via writeValue) at 20hz.
*/
NEVER,
};
explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
: mValuePool(valuePool) {}
~VehiclePropertyStore();
// Callback when a property value has been updated or a new value added.
using OnValueChangeCallback = std::function<void(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue&)>;
// Function that used to calculate unique token for given VehiclePropValue.
using TokenFunction = std::function<int64_t(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>;
// Register the given property according to the config. A property has to be registered first
// before write/read. If tokenFunc is not nullptr, it would be used to generate a unique
// property token to act as the key the property store. Otherwise, {propertyID, areaID} would be
// used as the key.
void registerProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config,
TokenFunction tokenFunc = nullptr) EXCLUDES(mLock);
// Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is
// true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value,
// 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
// override an existing value, the status for the existing value would be used for the
// overridden value.
// 'EventMode' controls whether the 'OnValueChangeCallback' will be called for this operation.
// If 'useCurrentTimestamp' is true, the property value will be set to the current timestamp.
VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
bool updateStatus = false,
EventMode mode = EventMode::ON_VALUE_CHANGE,
bool useCurrentTimestamp = false) EXCLUDES(mLock);
// Remove a given property value from the property store. The 'propValue' would be used to
// generate the key for the value to remove.
void removeValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue)
EXCLUDES(mLock);
// Remove all the values for the property.
void removeValuesForProperty(int32_t propId) EXCLUDES(mLock);
// Read all the stored values.
std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const EXCLUDES(mLock);
// Read all the values for the property.
ValuesResultType readValuesForProperty(int32_t propId) const EXCLUDES(mLock);
// Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the
// value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is
// not configured.
ValueResultType readValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const
EXCLUDES(mLock);
// Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the
// value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is
// not configured.
ValueResultType readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const
EXCLUDES(mLock);
// Get all property configs.
std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs()
const EXCLUDES(mLock);
// Get the property config for the requested property.
android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*,
VhalError>
getConfig(int32_t propId) const EXCLUDES(mLock);
// Set a callback that would be called when a property value has been updated.
void setOnValueChangeCallback(const OnValueChangeCallback& callback) EXCLUDES(mLock);
inline std::shared_ptr<VehiclePropValuePool> getValuePool() { return mValuePool; }
private:
struct RecordId {
int32_t area;
int64_t token;
std::string toString() const;
bool operator==(const RecordId& other) const;
};
struct RecordIdHash {
size_t operator()(RecordId const& recordId) const;
};
struct Record {
aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig;
TokenFunction tokenFunction;
std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values;
};
// {@code VehiclePropValuePool} is thread-safe.
std::shared_ptr<VehiclePropValuePool> mValuePool;
mutable std::mutex mLock;
std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock);
OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock);
const Record* getRecordLocked(int32_t propId) const;
Record* getRecordLocked(int32_t propId);
RecordId getRecordIdLocked(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
const Record& record) const;
ValueResultType readValueLocked(const RecordId& recId, const Record& record) const;
};
} // namespace vehicle
} // namespace automotive
} // namespace hardware
} // namespace android
#endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_