• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_VehicleUtils_H_
18 #define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
19 
20 #include <VehicleHalTypes.h>
21 
22 #include <android-base/format.h>
23 #include <android-base/result.h>
24 #include <math/HashCombine.h>
25 #include <utils/Log.h>
26 
27 namespace android {
28 namespace hardware {
29 namespace automotive {
30 namespace vehicle {
31 
32 // Represents all supported areas for a property.
33 constexpr int32_t kAllSupportedAreas = 0;
34 
35 // Returns underlying (integer) value for given enum.
36 template <typename ENUM, typename U = typename std::underlying_type<ENUM>::type>
toInt(ENUM const value)37 inline constexpr U toInt(ENUM const value) {
38     return static_cast<U>(value);
39 }
40 
getPropType(int32_t prop)41 inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyType getPropType(
42         int32_t prop) {
43     return static_cast<aidl::android::hardware::automotive::vehicle::VehiclePropertyType>(
44             prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MASK));
45 }
46 
getPropGroup(int32_t prop)47 inline constexpr aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup getPropGroup(
48         int32_t prop) {
49     return static_cast<aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup>(
50             prop & toInt(aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::MASK));
51 }
52 
getPropArea(int32_t prop)53 inline constexpr aidl::android::hardware::automotive::vehicle::VehicleArea getPropArea(
54         int32_t prop) {
55     return static_cast<aidl::android::hardware::automotive::vehicle::VehicleArea>(
56             prop & toInt(aidl::android::hardware::automotive::vehicle::VehicleArea::MASK));
57 }
58 
isGlobalProp(int32_t prop)59 inline constexpr bool isGlobalProp(int32_t prop) {
60     return getPropArea(prop) == aidl::android::hardware::automotive::vehicle::VehicleArea::GLOBAL;
61 }
62 
isSystemProp(int32_t prop)63 inline constexpr bool isSystemProp(int32_t prop) {
64     return aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup::SYSTEM ==
65            getPropGroup(prop);
66 }
67 
getAreaConfig(int32_t propId,int32_t areaId,const aidl::android::hardware::automotive::vehicle::VehiclePropConfig & config)68 inline const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* getAreaConfig(
69         int32_t propId, int32_t areaId,
70         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config) {
71     if (config.areaConfigs.size() == 0) {
72         return nullptr;
73     }
74 
75     if (isGlobalProp(propId)) {
76         return &(config.areaConfigs[0]);
77     }
78 
79     for (const auto& c : config.areaConfigs) {
80         if (c.areaId == areaId) {
81             return &c;
82         }
83     }
84     return nullptr;
85 }
86 
getAreaConfig(const aidl::android::hardware::automotive::vehicle::VehiclePropValue & propValue,const aidl::android::hardware::automotive::vehicle::VehiclePropConfig & config)87 inline const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* getAreaConfig(
88         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
89         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config) {
90     return getAreaConfig(propValue.prop, propValue.areaId, config);
91 }
92 
93 inline std::unique_ptr<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
createVehiclePropValueVec(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,size_t vecSize)94 createVehiclePropValueVec(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
95                           size_t vecSize) {
96     auto val = std::unique_ptr<aidl::android::hardware::automotive::vehicle::VehiclePropValue>(
97             new aidl::android::hardware::automotive::vehicle::VehiclePropValue);
98     switch (type) {
99         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
100             [[fallthrough]];
101         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
102             vecSize = 1;
103             [[fallthrough]];
104         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
105             val->value.int32Values.resize(vecSize);
106             break;
107         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
108             vecSize = 1;
109             [[fallthrough]];
110         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
111             val->value.floatValues.resize(vecSize);
112             break;
113         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
114             vecSize = 1;
115             [[fallthrough]];
116         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
117             val->value.int64Values.resize(vecSize);
118             break;
119         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
120             val->value.byteValues.resize(vecSize);
121             break;
122         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
123         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
124             break;  // Valid, but nothing to do.
125         default:
126             ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
127     }
128     return val;
129 }
130 
131 inline std::unique_ptr<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
createVehiclePropValue(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type)132 createVehiclePropValue(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
133     return createVehiclePropValueVec(type, 1);
134 }
135 
getVehicleRawValueVectorSize(const aidl::android::hardware::automotive::vehicle::RawPropValues & value,aidl::android::hardware::automotive::vehicle::VehiclePropertyType type)136 inline size_t getVehicleRawValueVectorSize(
137         const aidl::android::hardware::automotive::vehicle::RawPropValues& value,
138         aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
139     switch (type) {
140         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
141             [[fallthrough]];
142         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
143             return std::min(value.int32Values.size(), static_cast<size_t>(1));
144         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
145             return std::min(value.floatValues.size(), static_cast<size_t>(1));
146         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
147             return std::min(value.int64Values.size(), static_cast<size_t>(1));
148         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
149             return value.int32Values.size();
150         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
151             return value.floatValues.size();
152         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
153             return value.int64Values.size();
154         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
155             return value.byteValues.size();
156         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
157             [[fallthrough]];
158         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
159             return 0;
160         default:
161             ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type));
162             return 0;
163     }
164 }
165 
copyVehicleRawValue(aidl::android::hardware::automotive::vehicle::RawPropValues * dest,const aidl::android::hardware::automotive::vehicle::RawPropValues & src)166 inline void copyVehicleRawValue(
167         aidl::android::hardware::automotive::vehicle::RawPropValues* dest,
168         const aidl::android::hardware::automotive::vehicle::RawPropValues& src) {
169     dest->int32Values = src.int32Values;
170     dest->floatValues = src.floatValues;
171     dest->int64Values = src.int64Values;
172     dest->byteValues = src.byteValues;
173     dest->stringValue = src.stringValue;
174 }
175 
176 // getVehiclePropValueSize returns approximately how much memory 'value' would take. This should
177 // only be used in a limited-size memory pool to set an upper bound for memory consumption.
getVehiclePropValueSize(const aidl::android::hardware::automotive::vehicle::VehiclePropValue & prop)178 inline size_t getVehiclePropValueSize(
179         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) {
180     size_t size = 0;
181     size += sizeof(prop.timestamp);
182     size += sizeof(prop.areaId);
183     size += sizeof(prop.prop);
184     size += sizeof(prop.status);
185     size += prop.value.int32Values.size() * sizeof(int32_t);
186     size += prop.value.int64Values.size() * sizeof(int64_t);
187     size += prop.value.floatValues.size() * sizeof(float);
188     size += prop.value.byteValues.size() * sizeof(uint8_t);
189     size += prop.value.stringValue.size();
190     return size;
191 }
192 
193 // Check whether the value is valid according to config.
194 // We check for the following:
195 // *  If the type is INT32, {@code value.int32Values} must contain one element.
196 // *  If the type is INT32_VEC, {@code value.int32Values} must contain at least one element.
197 // *  If the type is INT64, {@code value.int64Values} must contain one element.
198 // *  If the type is INT64_VEC, {@code value.int64Values} must contain at least one element.
199 // *  If the type is FLOAT, {@code value.floatValues} must contain one element.
200 // *  If the type is FLOAT_VEC, {@code value.floatValues} must contain at least one element.
201 // *  If the type is MIXED, see checkVendorMixedPropValue.
202 android::base::Result<void> checkPropValue(
203         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
204         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
205 
206 // Check whether the Mixed type value is valid according to config.
207 // We check for the following:
208 // *  configArray[1] + configArray[2] + configArray[3] must be equal to the number of
209 //    {@code value.int32Values} elements.
210 // *  configArray[4] + configArray[5] must be equal to the number of {@code value.int64Values}
211 //    elements.
212 // *  configArray[6] + configArray[7] must be equal to the number of {@code value.floatValues}
213 //    elements.
214 // *  configArray[8] must be equal to the number of {@code value.byteValues} elements.
215 android::base::Result<void> checkVendorMixedPropValue(
216         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
217         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
218 
219 // Check whether the value is within the configured range.
220 // We check for the following types:
221 // *  If type is INT32 or INT32_VEC, all {@code value.int32Values} elements must be within
222 //    {@code minInt32Value} and {@code maxInt32Value} if either of them is not 0.
223 // *  If type is INT64 or INT64_VEC, all {@code value.int64Values} elements must be within
224 //    {@code minInt64Value} and {@code maxInt64Value} if either of them is not 0.
225 // *  If type is FLOAT or FLOAT_VEC, all {@code value.floatValues} elements must be within
226 //    {@code minFloatValues} and {@code maxFloatValues} if either of them is not 0.
227 // We don't check other types. If more checks are required, they should be added in VehicleHardware
228 // implementation.
229 android::base::Result<void> checkValueRange(
230         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
231         const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* config);
232 
233 // VhalError is a wrapper class for {@code StatusCode} that could act as E in {@code Result<T,E>}.
234 class VhalError final {
235   public:
VhalError()236     VhalError() : mCode(aidl::android::hardware::automotive::vehicle::StatusCode::OK) {}
237 
VhalError(aidl::android::hardware::automotive::vehicle::StatusCode && code)238     VhalError(aidl::android::hardware::automotive::vehicle::StatusCode&& code) : mCode(code) {}
239 
VhalError(const aidl::android::hardware::automotive::vehicle::StatusCode & code)240     VhalError(const aidl::android::hardware::automotive::vehicle::StatusCode& code) : mCode(code) {}
241 
242     aidl::android::hardware::automotive::vehicle::StatusCode value() const;
243 
StatusCode()244     inline operator aidl::android::hardware::automotive::vehicle::StatusCode() const {
245         return value();
246     }
247 
248     std::string print() const;
249 
250   private:
251     aidl::android::hardware::automotive::vehicle::StatusCode mCode;
252 };
253 
254 // VhalResult is a {@code Result} that contains {@code StatusCode} as error type.
255 template <class T>
256 using VhalResult = android::base::Result<T, VhalError>;
257 
258 // StatusError could be cast to {@code ResultError} with a {@code StatusCode} and should be used
259 // as error type for {@VhalResult}.
260 using StatusError = android::base::Error<VhalError>;
261 
262 template <class T>
getErrorCode(const VhalResult<T> & result)263 aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(const VhalResult<T>& result) {
264     if (result.ok()) {
265         return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
266     }
267     return result.error().code();
268 }
269 
270 template <class T>
getIntErrorCode(const VhalResult<T> & result)271 int getIntErrorCode(const VhalResult<T>& result) {
272     return toInt(getErrorCode(result));
273 }
274 
275 template <class T, class E>
getErrorMsg(const android::base::Result<T,E> & result)276 std::string getErrorMsg(const android::base::Result<T, E>& result) {
277     if (result.ok()) {
278         return "";
279     }
280     return result.error().message();
281 }
282 
283 template <class T, class E>
toScopedAStatus(const android::base::Result<T,E> & result,aidl::android::hardware::automotive::vehicle::StatusCode status,const std::string & additionalErrorMsg)284 ndk::ScopedAStatus toScopedAStatus(const android::base::Result<T, E>& result,
285                                    aidl::android::hardware::automotive::vehicle::StatusCode status,
286                                    const std::string& additionalErrorMsg) {
287     if (result.ok()) {
288         return ndk::ScopedAStatus::ok();
289     }
290     return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
291             toInt(status),
292             fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
293 }
294 
295 template <class T, class E>
toScopedAStatus(const android::base::Result<T,E> & result,aidl::android::hardware::automotive::vehicle::StatusCode status)296 ndk::ScopedAStatus toScopedAStatus(
297         const android::base::Result<T, E>& result,
298         aidl::android::hardware::automotive::vehicle::StatusCode status) {
299     return toScopedAStatus(result, status, "");
300 }
301 
302 template <class T>
toScopedAStatus(const VhalResult<T> & result)303 ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result) {
304     return toScopedAStatus(result, getErrorCode(result));
305 }
306 
307 template <class T>
toScopedAStatus(const VhalResult<T> & result,const std::string & additionalErrorMsg)308 ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result,
309                                    const std::string& additionalErrorMsg) {
310     return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
311 }
312 
313 struct PropIdAreaId {
314     int32_t propId;
315     int32_t areaId;
316 
317     inline bool operator==(const PropIdAreaId& other) const {
318         return areaId == other.areaId && propId == other.propId;
319     }
320 };
321 
322 struct PropIdAreaIdHash {
operatorPropIdAreaIdHash323     inline size_t operator()(const PropIdAreaId& propIdAreaId) const {
324         size_t res = 0;
325         hashCombine(res, propIdAreaId.propId);
326         hashCombine(res, propIdAreaId.areaId);
327         return res;
328     }
329 };
330 
331 // This is for debug purpose only.
propIdToString(int32_t propId)332 inline std::string propIdToString(int32_t propId) {
333     return toString(
334             static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
335 }
336 
337 // This is for debug purpose only.
338 android::base::Result<int32_t> stringToPropId(const std::string& propName);
339 
340 template <typename T>
roundToNearestResolution(std::vector<T> & arrayToSanitize,float resolution)341 void roundToNearestResolution(std::vector<T>& arrayToSanitize, float resolution) {
342     if (resolution == 0) {
343         return;
344     }
345     for (size_t i = 0; i < arrayToSanitize.size(); i++) {
346         arrayToSanitize[i] = (T)((std::round(arrayToSanitize[i] / resolution)) * resolution);
347     }
348 }
349 
sanitizeByResolution(aidl::android::hardware::automotive::vehicle::RawPropValues * value,float resolution)350 inline void sanitizeByResolution(aidl::android::hardware::automotive::vehicle::RawPropValues* value,
351                                  float resolution) {
352     roundToNearestResolution(value->int32Values, resolution);
353     roundToNearestResolution(value->floatValues, resolution);
354     roundToNearestResolution(value->int64Values, resolution);
355 }
356 
357 }  // namespace vehicle
358 }  // namespace automotive
359 }  // namespace hardware
360 }  // namespace android
361 
362 #endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
363