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