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