1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ 18 #define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ 19 20 #include <cstdint> 21 #include <map> 22 #include <memory> 23 #include <mutex> 24 #include <unordered_map> 25 26 #include <VehicleHalTypes.h> 27 #include <VehicleObjectPool.h> 28 #include <VehicleUtils.h> 29 #include <android-base/result.h> 30 #include <android-base/thread_annotations.h> 31 32 namespace android { 33 namespace hardware { 34 namespace automotive { 35 namespace vehicle { 36 37 // Encapsulates work related to storing and accessing configuration, storing and modifying 38 // vehicle property values. 39 // 40 // VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g. 41 // to get value for all areas for particular property. 42 // 43 // This class is thread-safe, however it uses blocking synchronization across all methods. 44 class VehiclePropertyStore final { 45 public: 46 using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>; 47 using ValuesResultType = VhalResult<std::vector<VehiclePropValuePool::RecyclableType>>; 48 49 enum class EventMode : uint8_t { 50 /** 51 * Only invoke OnValueChangeCallback if the new property value (ignoring timestamp) is 52 * different than the existing value. 53 * 54 * This should be used for regular cases. 55 */ 56 ON_VALUE_CHANGE, 57 /** 58 * Always invoke OnValueChangeCallback. 59 * 60 * This should be used for the special properties that are used for delivering event, e.g. 61 * HW_KEY_INPUT. 62 */ 63 ALWAYS, 64 /** 65 * Never invoke OnValueChangeCallback. 66 * 67 * This should be used for continuous property subscription when the sample rate for the 68 * subscription is smaller than the refresh rate for the property. E.g., the vehicle speed 69 * is refreshed at 20hz, but we are only subscribing at 10hz. In this case, we want to 70 * generate the property change event at 10hz, not 20hz, but we still want to refresh the 71 * timestamp (via writeValue) at 20hz. 72 */ 73 NEVER, 74 }; 75 VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)76 explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool) 77 : mValuePool(valuePool) {} 78 79 ~VehiclePropertyStore(); 80 81 // Callback when a property value has been updated or a new value added. 82 using OnValueChangeCallback = std::function<void( 83 const aidl::android::hardware::automotive::vehicle::VehiclePropValue&)>; 84 85 // Function that used to calculate unique token for given VehiclePropValue. 86 using TokenFunction = std::function<int64_t( 87 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>; 88 89 // Register the given property according to the config. A property has to be registered first 90 // before write/read. If tokenFunc is not nullptr, it would be used to generate a unique 91 // property token to act as the key the property store. Otherwise, {propertyID, areaID} would be 92 // used as the key. 93 void registerProperty( 94 const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config, 95 TokenFunction tokenFunc = nullptr); 96 97 // Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is 98 // true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value, 99 // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to 100 // override an existing value, the status for the existing value would be used for the 101 // overridden value. 102 // 'EventMode' controls whether the 'OnValueChangeCallback' will be called for this operation. 103 VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue, 104 bool updateStatus = false, 105 EventMode mode = EventMode::ON_VALUE_CHANGE); 106 107 // Remove a given property value from the property store. The 'propValue' would be used to 108 // generate the key for the value to remove. 109 void removeValue( 110 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue); 111 112 // Remove all the values for the property. 113 void removeValuesForProperty(int32_t propId); 114 115 // Read all the stored values. 116 std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const; 117 118 // Read all the values for the property. 119 ValuesResultType readValuesForProperty(int32_t propId) const; 120 121 // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the 122 // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is 123 // not configured. 124 ValueResultType readValue( 125 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const; 126 127 // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the 128 // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is 129 // not configured. 130 ValueResultType readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const; 131 132 // Get all property configs. 133 std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs() 134 const; 135 136 // Get the property config for the requested property. 137 android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*, 138 VhalError> 139 getConfig(int32_t propId) const; 140 141 // Set a callback that would be called when a property value has been updated. 142 void setOnValueChangeCallback(const OnValueChangeCallback& callback); 143 getValuePool()144 inline std::shared_ptr<VehiclePropValuePool> getValuePool() { return mValuePool; } 145 146 private: 147 struct RecordId { 148 int32_t area; 149 int64_t token; 150 151 std::string toString() const; 152 153 bool operator==(const RecordId& other) const; 154 }; 155 156 struct RecordIdHash { 157 size_t operator()(RecordId const& recordId) const; 158 }; 159 160 struct Record { 161 aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig; 162 TokenFunction tokenFunction; 163 std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values; 164 }; 165 166 // {@code VehiclePropValuePool} is thread-safe. 167 std::shared_ptr<VehiclePropValuePool> mValuePool; 168 mutable std::mutex mLock; 169 std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock); 170 OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock); 171 172 const Record* getRecordLocked(int32_t propId) const; 173 174 Record* getRecordLocked(int32_t propId); 175 176 RecordId getRecordIdLocked( 177 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue, 178 const Record& record) const; 179 180 ValueResultType readValueLocked(const RecordId& recId, const Record& record) const; 181 }; 182 183 } // namespace vehicle 184 } // namespace automotive 185 } // namespace hardware 186 } // namespace android 187 188 #endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ 189