xref: /aosp_15_r20/hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2017 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 #define LOG_TAG "VehiclePropertyStore"
17 #include <log/log.h>
18 #include <utils/SystemClock.h>
19 
20 #include <common/include/vhal_v2_0/VehicleUtils.h>
21 #include "VehiclePropertyStore.h"
22 
23 namespace android {
24 namespace hardware {
25 namespace automotive {
26 namespace vehicle {
27 namespace V2_0 {
28 
operator ==(const VehiclePropertyStore::RecordId & other) const29 bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
30     return prop == other.prop && area == other.area && token == other.token;
31 }
32 
operator <(const VehiclePropertyStore::RecordId & other) const33 bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const  {
34     return prop < other.prop
35            || (prop == other.prop && area < other.area)
36            || (prop == other.prop && area == other.area && token < other.token);
37 }
38 
registerProperty(const VehiclePropConfig & config,VehiclePropertyStore::TokenFunction tokenFunc)39 void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
40                                             VehiclePropertyStore::TokenFunction tokenFunc) {
41     MuxGuard g(mLock);
42     mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
43 }
44 
writeValueLocked(const VehiclePropValue & propValue,bool updateStatus)45 bool VehiclePropertyStore::writeValueLocked(const VehiclePropValue& propValue, bool updateStatus) {
46     if (!mConfigs.count(propValue.prop)) return false;
47 
48     RecordId recId = getRecordIdLocked(propValue);
49     VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
50     if (valueToUpdate == nullptr) {
51         mPropertyValues.insert({ recId, propValue });
52         return true;
53     }
54 
55     // propValue is outdated and drops it.
56     if (valueToUpdate->timestamp > propValue.timestamp) {
57         return false;
58     }
59     // update the propertyValue.
60     // The timestamp in propertyStore should only be updated by the server side. It indicates
61     // the time when the event is generated by the server.
62     valueToUpdate->timestamp = propValue.timestamp;
63     valueToUpdate->value = propValue.value;
64     if (updateStatus) {
65         valueToUpdate->status = propValue.status;
66     }
67     return true;
68 }
69 
writeValue(const VehiclePropValue & propValue,bool updateStatus)70 bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue, bool updateStatus) {
71     MuxGuard g(mLock);
72 
73     return writeValueLocked(propValue, updateStatus);
74 }
75 
writeValueWithCurrentTimestamp(VehiclePropValue * propValuePtr,bool updateStatus)76 bool VehiclePropertyStore::writeValueWithCurrentTimestamp(VehiclePropValue* propValuePtr,
77                                                           bool updateStatus) {
78     MuxGuard g(mLock);
79 
80     propValuePtr->timestamp = elapsedRealtimeNano();
81     return writeValueLocked(*propValuePtr, updateStatus);
82 }
83 
refreshTimestamp(int32_t propId,int32_t areaId)84 std::unique_ptr<VehiclePropValue> VehiclePropertyStore::refreshTimestamp(int32_t propId,
85                                                                          int32_t areaId) {
86     MuxGuard g(mLock);
87     RecordId recId = getRecordIdLocked(VehiclePropValue{
88             .prop = propId,
89             .areaId = areaId,
90     });
91     auto it = mPropertyValues.find(recId);
92     if (it == mPropertyValues.end()) {
93         return nullptr;
94     }
95 
96     it->second.timestamp = elapsedRealtimeNano();
97     return std::make_unique<VehiclePropValue>(it->second);
98 }
99 
removeValue(const VehiclePropValue & propValue)100 void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
101     MuxGuard g(mLock);
102     RecordId recId = getRecordIdLocked(propValue);
103     auto it = mPropertyValues.find(recId);
104     if (it != mPropertyValues.end()) {
105         mPropertyValues.erase(it);
106     }
107 }
108 
removeValuesForProperty(int32_t propId)109 void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
110     MuxGuard g(mLock);
111     auto range = findRangeLocked(propId);
112     mPropertyValues.erase(range.first, range.second);
113 }
114 
readAllValues() const115 std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
116     MuxGuard g(mLock);
117     std::vector<VehiclePropValue> allValues;
118     allValues.reserve(mPropertyValues.size());
119     for (auto&& it : mPropertyValues) {
120         allValues.push_back(it.second);
121     }
122     return allValues;
123 }
124 
readValuesForProperty(int32_t propId) const125 std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
126     std::vector<VehiclePropValue> values;
127     MuxGuard g(mLock);
128     auto range = findRangeLocked(propId);
129     for (auto it = range.first; it != range.second; ++it) {
130         values.push_back(it->second);
131     }
132 
133     return values;
134 }
135 
readValueOrNull(const VehiclePropValue & request) const136 std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
137         const VehiclePropValue& request) const {
138     MuxGuard g(mLock);
139     RecordId recId = getRecordIdLocked(request);
140     const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
141     return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
142 }
143 
readValueOrNull(int32_t prop,int32_t area,int64_t token) const144 std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
145         int32_t prop, int32_t area, int64_t token) const {
146     RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
147     MuxGuard g(mLock);
148     const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
149     return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
150 }
151 
152 
getAllConfigs() const153 std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
154     MuxGuard g(mLock);
155     std::vector<VehiclePropConfig> configs;
156     configs.reserve(mConfigs.size());
157     for (auto&& recordConfigIt: mConfigs) {
158         configs.push_back(recordConfigIt.second.propConfig);
159     }
160     return configs;
161 }
162 
getConfigOrNull(int32_t propId) const163 const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
164     MuxGuard g(mLock);
165     auto recordConfigIt = mConfigs.find(propId);
166     return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
167 }
168 
getConfigOrDie(int32_t propId) const169 const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
170     auto cfg = getConfigOrNull(propId);
171     if (!cfg) {
172         ALOGW("%s: config not found for property: 0x%x", __func__, propId);
173         abort();
174     }
175     return cfg;
176 }
177 
getRecordIdLocked(const VehiclePropValue & valuePrototype) const178 VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
179         const VehiclePropValue& valuePrototype) const {
180     RecordId recId = {
181         .prop = valuePrototype.prop,
182         .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
183         .token = 0
184     };
185 
186     auto it = mConfigs.find(recId.prop);
187     if (it == mConfigs.end()) return {};
188 
189     if (it->second.tokenFunction != nullptr) {
190         recId.token = it->second.tokenFunction(valuePrototype);
191     }
192     return recId;
193 }
194 
getValueOrNullLocked(const VehiclePropertyStore::RecordId & recId) const195 const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
196         const VehiclePropertyStore::RecordId& recId) const  {
197     auto it = mPropertyValues.find(recId);
198     return it == mPropertyValues.end() ? nullptr : &it->second;
199 }
200 
findRangeLocked(int32_t propId) const201 VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
202     // Based on the fact that mPropertyValues is a sorted map by RecordId.
203     auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
204     auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });
205 
206     return  PropertyMapRange { beginIt, endIt };
207 }
208 
209 }  // namespace V2_0
210 }  // namespace vehicle
211 }  // namespace automotive
212 }  // namespace hardware
213 }  // namespace android
214