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
19 #include <common/include/vhal_v2_0/VehicleUtils.h>
20 #include "VehiclePropertyStore.h"
21
22 namespace android {
23 namespace hardware {
24 namespace automotive {
25 namespace vehicle {
26 namespace V2_0 {
27
operator ==(const VehiclePropertyStore::RecordId & other) const28 bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
29 return prop == other.prop && area == other.area && token == other.token;
30 }
31
operator <(const VehiclePropertyStore::RecordId & other) const32 bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const {
33 return prop < other.prop
34 || (prop == other.prop && area < other.area)
35 || (prop == other.prop && area == other.area && token < other.token);
36 }
37
registerProperty(const VehiclePropConfig & config,VehiclePropertyStore::TokenFunction tokenFunc)38 void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
39 VehiclePropertyStore::TokenFunction tokenFunc) {
40 MuxGuard g(mLock);
41 mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
42 }
43
writeValue(const VehiclePropValue & propValue,bool updateStatus)44 bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
45 bool updateStatus) {
46 MuxGuard g(mLock);
47 if (!mConfigs.count(propValue.prop)) return false;
48
49 RecordId recId = getRecordIdLocked(propValue);
50 VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
51 if (valueToUpdate == nullptr) {
52 mPropertyValues.insert({ recId, propValue });
53 return true;
54 }
55
56 // propValue is outdated and drops it.
57 if (valueToUpdate->timestamp > propValue.timestamp) {
58 return false;
59 }
60 // update the propertyValue.
61 // The timestamp in propertyStore should only be updated by the server side. It indicates
62 // the time when the event is generated by the server.
63 valueToUpdate->timestamp = propValue.timestamp;
64 valueToUpdate->value = propValue.value;
65 if (updateStatus) {
66 valueToUpdate->status = propValue.status;
67 }
68 return true;
69 }
70
removeValue(const VehiclePropValue & propValue)71 void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
72 MuxGuard g(mLock);
73 RecordId recId = getRecordIdLocked(propValue);
74 auto it = mPropertyValues.find(recId);
75 if (it != mPropertyValues.end()) {
76 mPropertyValues.erase(it);
77 }
78 }
79
removeValuesForProperty(int32_t propId)80 void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
81 MuxGuard g(mLock);
82 auto range = findRangeLocked(propId);
83 mPropertyValues.erase(range.first, range.second);
84 }
85
readAllValues() const86 std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
87 MuxGuard g(mLock);
88 std::vector<VehiclePropValue> allValues;
89 allValues.reserve(mPropertyValues.size());
90 for (auto&& it : mPropertyValues) {
91 allValues.push_back(it.second);
92 }
93 return allValues;
94 }
95
readValuesForProperty(int32_t propId) const96 std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
97 std::vector<VehiclePropValue> values;
98 MuxGuard g(mLock);
99 auto range = findRangeLocked(propId);
100 for (auto it = range.first; it != range.second; ++it) {
101 values.push_back(it->second);
102 }
103
104 return values;
105 }
106
readValueOrNull(const VehiclePropValue & request) const107 std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
108 const VehiclePropValue& request) const {
109 MuxGuard g(mLock);
110 RecordId recId = getRecordIdLocked(request);
111 const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
112 return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
113 }
114
readValueOrNull(int32_t prop,int32_t area,int64_t token) const115 std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
116 int32_t prop, int32_t area, int64_t token) const {
117 RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
118 MuxGuard g(mLock);
119 const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
120 return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
121 }
122
123
getAllConfigs() const124 std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
125 MuxGuard g(mLock);
126 std::vector<VehiclePropConfig> configs;
127 configs.reserve(mConfigs.size());
128 for (auto&& recordConfigIt: mConfigs) {
129 configs.push_back(recordConfigIt.second.propConfig);
130 }
131 return configs;
132 }
133
getConfigOrNull(int32_t propId) const134 const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
135 MuxGuard g(mLock);
136 auto recordConfigIt = mConfigs.find(propId);
137 return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
138 }
139
getConfigOrDie(int32_t propId) const140 const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
141 auto cfg = getConfigOrNull(propId);
142 if (!cfg) {
143 ALOGW("%s: config not found for property: 0x%x", __func__, propId);
144 abort();
145 }
146 return cfg;
147 }
148
getRecordIdLocked(const VehiclePropValue & valuePrototype) const149 VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
150 const VehiclePropValue& valuePrototype) const {
151 RecordId recId = {
152 .prop = valuePrototype.prop,
153 .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
154 .token = 0
155 };
156
157 auto it = mConfigs.find(recId.prop);
158 if (it == mConfigs.end()) return {};
159
160 if (it->second.tokenFunction != nullptr) {
161 recId.token = it->second.tokenFunction(valuePrototype);
162 }
163 return recId;
164 }
165
getValueOrNullLocked(const VehiclePropertyStore::RecordId & recId) const166 const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
167 const VehiclePropertyStore::RecordId& recId) const {
168 auto it = mPropertyValues.find(recId);
169 return it == mPropertyValues.end() ? nullptr : &it->second;
170 }
171
findRangeLocked(int32_t propId) const172 VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
173 // Based on the fact that mPropertyValues is a sorted map by RecordId.
174 auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
175 auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });
176
177 return PropertyMapRange { beginIt, endIt };
178 }
179
180 } // namespace V2_0
181 } // namespace vehicle
182 } // namespace automotive
183 } // namespace hardware
184 } // namespace android
185