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 or OnValuesChangeCallback if the new property value 52 * (ignoring timestamp) is different than the existing value. 53 * 54 * This should be used for regular cases. 55 */ 56 ON_VALUE_CHANGE, 57 /** 58 * Always invoke OnValueChangeCallback or OnValuesChangeCallback. 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 or OnValuesChangeCalblack. 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 // Callback when one or more property values have been updated or new values added. 86 using OnValuesChangeCallback = std::function<void( 87 std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>)>; 88 89 // Function that used to calculate unique token for given VehiclePropValue. 90 using TokenFunction = std::function<int64_t( 91 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>; 92 93 // Register the given property according to the config. A property has to be registered first 94 // before write/read. If tokenFunc is not nullptr, it would be used to generate a unique 95 // property token to act as the key the property store. Otherwise, {propertyID, areaID} would be 96 // used as the key. 97 void registerProperty( 98 const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config, 99 TokenFunction tokenFunc = nullptr) EXCLUDES(mLock); 100 101 // Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is 102 // true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value, 103 // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to 104 // override an existing value, the status for the existing value would be used for the 105 // overridden value. 106 // 'EventMode' controls whether the 'OnValueChangeCallback' or 'OnValuesChangeCallback' will be 107 // called for this operation. 108 // If 'useCurrentTimestamp' is true, the property value will be set to the current timestamp. 109 VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue, 110 bool updateStatus = false, 111 EventMode mode = EventMode::ON_VALUE_CHANGE, 112 bool useCurrentTimestamp = false) EXCLUDES(mLock); 113 114 // Refresh the timestamp for the stored property value for [propId, areaId]. If eventMode is 115 // always, generates the property update event, otherwise, only update the stored timestamp 116 // without generating event. This operation is atomic with other writeValue operations. 117 void refreshTimestamp(int32_t propId, int32_t areaId, EventMode eventMode) EXCLUDES(mLock); 118 119 // Refresh the timestamp for multiple [propId, areaId]s. 120 void refreshTimestamps( 121 std::unordered_map<PropIdAreaId, EventMode, PropIdAreaIdHash> eventModeByPropIdAreaId) 122 EXCLUDES(mLock); 123 124 // Remove a given property value from the property store. The 'propValue' would be used to 125 // generate the key for the value to remove. 126 void removeValue( 127 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue) 128 EXCLUDES(mLock); 129 130 // Remove all the values for the property. 131 void removeValuesForProperty(int32_t propId) EXCLUDES(mLock); 132 133 // Read all the stored values. 134 std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const EXCLUDES(mLock); 135 136 // Read all the values for the property. 137 ValuesResultType readValuesForProperty(int32_t propId) const EXCLUDES(mLock); 138 139 // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the 140 // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is 141 // not configured. 142 ValueResultType readValue( 143 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const 144 EXCLUDES(mLock); 145 146 // Read the value for the requested property. Returns {@code StatusCode::NOT_AVAILABLE} if the 147 // value has not been set yet. Returns {@code StatusCode::INVALID_ARG} if the property is 148 // not configured. 149 ValueResultType readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const 150 EXCLUDES(mLock); 151 152 // Get all property configs. 153 std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs() 154 const EXCLUDES(mLock); 155 156 // Deprecated, use getPropConfig instead. This is unsafe to use if registerProperty overwrites 157 // an existing config. 158 android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*, 159 VhalError> 160 getConfig(int32_t propId) const EXCLUDES(mLock); 161 162 // Get the property config for the requested property. 163 android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropConfig, 164 VhalError> 165 getPropConfig(int32_t propId) const EXCLUDES(mLock); 166 167 // Set a callback that would be called when a property value has been updated. 168 void setOnValueChangeCallback(const OnValueChangeCallback& callback) EXCLUDES(mLock); 169 170 // Set a callback that would be called when one or more property values have been updated. 171 // For backward compatibility, this is optional. If this is not set, then multiple property 172 // updates will be delivered through multiple OnValueChangeCallback instead. 173 // It is recommended to set this and batch the property update events for better performance. 174 // If this is set, then OnValueChangeCallback will not be used. 175 void setOnValuesChangeCallback(const OnValuesChangeCallback& callback) EXCLUDES(mLock); 176 getValuePool()177 inline std::shared_ptr<VehiclePropValuePool> getValuePool() { return mValuePool; } 178 179 private: 180 struct RecordId { 181 int32_t area; 182 int64_t token; 183 184 std::string toString() const; 185 186 bool operator==(const RecordId& other) const; 187 }; 188 189 struct RecordIdHash { 190 size_t operator()(RecordId const& recordId) const; 191 }; 192 193 struct Record { 194 aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig; 195 TokenFunction tokenFunction; 196 std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values; 197 }; 198 199 // {@code VehiclePropValuePool} is thread-safe. 200 std::shared_ptr<VehiclePropValuePool> mValuePool; 201 mutable std::mutex mLock; 202 std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock); 203 OnValueChangeCallback mOnValueChangeCallback GUARDED_BY(mLock); 204 OnValuesChangeCallback mOnValuesChangeCallback GUARDED_BY(mLock); 205 206 const Record* getRecordLocked(int32_t propId) const; 207 208 Record* getRecordLocked(int32_t propId); 209 210 RecordId getRecordIdLocked( 211 const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue, 212 const Record& record) const; 213 214 ValueResultType readValueLocked(const RecordId& recId, const Record& record) const; 215 }; 216 217 } // namespace vehicle 218 } // namespace automotive 219 } // namespace hardware 220 } // namespace android 221 222 #endif // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehiclePropertyStore_H_ 223