• 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             val.reset(nullptr);
128     }
129     return val;
130 }
131 
132 inline std::unique_ptr<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
createVehiclePropValue(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type)133 createVehiclePropValue(aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
134     return createVehiclePropValueVec(type, 1);
135 }
136 
getVehicleRawValueVectorSize(const aidl::android::hardware::automotive::vehicle::RawPropValues & value,aidl::android::hardware::automotive::vehicle::VehiclePropertyType type)137 inline size_t getVehicleRawValueVectorSize(
138         const aidl::android::hardware::automotive::vehicle::RawPropValues& value,
139         aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
140     switch (type) {
141         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
142             [[fallthrough]];
143         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
144             return std::min(value.int32Values.size(), static_cast<size_t>(1));
145         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
146             return std::min(value.floatValues.size(), static_cast<size_t>(1));
147         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
148             return std::min(value.int64Values.size(), static_cast<size_t>(1));
149         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
150             return value.int32Values.size();
151         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
152             return value.floatValues.size();
153         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
154             return value.int64Values.size();
155         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
156             return value.byteValues.size();
157         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
158             [[fallthrough]];
159         case aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
160             return 0;
161         default:
162             ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type));
163             return 0;
164     }
165 }
166 
copyVehicleRawValue(aidl::android::hardware::automotive::vehicle::RawPropValues * dest,const aidl::android::hardware::automotive::vehicle::RawPropValues & src)167 inline void copyVehicleRawValue(
168         aidl::android::hardware::automotive::vehicle::RawPropValues* dest,
169         const aidl::android::hardware::automotive::vehicle::RawPropValues& src) {
170     dest->int32Values = src.int32Values;
171     dest->floatValues = src.floatValues;
172     dest->int64Values = src.int64Values;
173     dest->byteValues = src.byteValues;
174     dest->stringValue = src.stringValue;
175 }
176 
177 // getVehiclePropValueSize returns approximately how much memory 'value' would take. This should
178 // 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)179 inline size_t getVehiclePropValueSize(
180         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) {
181     size_t size = 0;
182     size += sizeof(prop.timestamp);
183     size += sizeof(prop.areaId);
184     size += sizeof(prop.prop);
185     size += sizeof(prop.status);
186     size += prop.value.int32Values.size() * sizeof(int32_t);
187     size += prop.value.int64Values.size() * sizeof(int64_t);
188     size += prop.value.floatValues.size() * sizeof(float);
189     size += prop.value.byteValues.size() * sizeof(uint8_t);
190     size += prop.value.stringValue.size();
191     return size;
192 }
193 
194 // Check whether the value is valid according to config.
195 // We check for the following:
196 // *  If the type is INT32, {@code value.int32Values} must contain one element.
197 // *  If the type is INT32_VEC, {@code value.int32Values} must contain at least one element.
198 // *  If the type is INT64, {@code value.int64Values} must contain one element.
199 // *  If the type is INT64_VEC, {@code value.int64Values} must contain at least one element.
200 // *  If the type is FLOAT, {@code value.floatValues} must contain one element.
201 // *  If the type is FLOAT_VEC, {@code value.floatValues} must contain at least one element.
202 // *  If the type is MIXED, see checkVendorMixedPropValue.
203 android::base::Result<void> checkPropValue(
204         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
205         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
206 
207 // Check whether the Mixed type value is valid according to config.
208 // We check for the following:
209 // *  configArray[1] + configArray[2] + configArray[3] must be equal to the number of
210 //    {@code value.int32Values} elements.
211 // *  configArray[4] + configArray[5] must be equal to the number of {@code value.int64Values}
212 //    elements.
213 // *  configArray[6] + configArray[7] must be equal to the number of {@code value.floatValues}
214 //    elements.
215 // *  configArray[8] must be equal to the number of {@code value.byteValues} elements.
216 android::base::Result<void> checkVendorMixedPropValue(
217         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
218         const aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
219 
220 // Check whether the value is within the configured range.
221 // We check for the following types:
222 // *  If type is INT32 or INT32_VEC, all {@code value.int32Values} elements must be within
223 //    {@code minInt32Value} and {@code maxInt32Value} if either of them is not 0.
224 // *  If type is INT64 or INT64_VEC, all {@code value.int64Values} elements must be within
225 //    {@code minInt64Value} and {@code maxInt64Value} if either of them is not 0.
226 // *  If type is FLOAT or FLOAT_VEC, all {@code value.floatValues} elements must be within
227 //    {@code minFloatValues} and {@code maxFloatValues} if either of them is not 0.
228 // We don't check other types. If more checks are required, they should be added in VehicleHardware
229 // implementation.
230 android::base::Result<void> checkValueRange(
231         const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
232         const aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* config);
233 
234 // VhalError is a wrapper class for {@code StatusCode} that could act as E in {@code Result<T,E>}.
235 class VhalError final {
236   public:
VhalError()237     VhalError() : mCode(aidl::android::hardware::automotive::vehicle::StatusCode::OK) {}
238 
VhalError(aidl::android::hardware::automotive::vehicle::StatusCode && code)239     VhalError(aidl::android::hardware::automotive::vehicle::StatusCode&& code) : mCode(code) {}
240 
VhalError(const aidl::android::hardware::automotive::vehicle::StatusCode & code)241     VhalError(const aidl::android::hardware::automotive::vehicle::StatusCode& code) : mCode(code) {}
242 
243     aidl::android::hardware::automotive::vehicle::StatusCode value() const;
244 
StatusCode()245     inline operator aidl::android::hardware::automotive::vehicle::StatusCode() const {
246         return value();
247     }
248 
249     std::string print() const;
250 
251   private:
252     aidl::android::hardware::automotive::vehicle::StatusCode mCode;
253 };
254 
255 // VhalResult is a {@code Result} that contains {@code StatusCode} as error type.
256 template <class T>
257 using VhalResult = android::base::Result<T, VhalError>;
258 
259 // StatusError could be cast to {@code ResultError} with a {@code StatusCode} and should be used
260 // as error type for {@VhalResult}.
261 using StatusError = android::base::Error<VhalError>;
262 
263 template <class T>
getErrorCode(const VhalResult<T> & result)264 aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(const VhalResult<T>& result) {
265     if (result.ok()) {
266         return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
267     }
268     return result.error().code();
269 }
270 
271 template <class T>
getIntErrorCode(const VhalResult<T> & result)272 int getIntErrorCode(const VhalResult<T>& result) {
273     return toInt(getErrorCode(result));
274 }
275 
276 template <class T, class E>
getErrorMsg(const android::base::Result<T,E> & result)277 std::string getErrorMsg(const android::base::Result<T, E>& result) {
278     if (result.ok()) {
279         return "";
280     }
281     return result.error().message();
282 }
283 
284 template <class T, class E>
toScopedAStatus(const android::base::Result<T,E> & result,aidl::android::hardware::automotive::vehicle::StatusCode status,const std::string & additionalErrorMsg)285 ndk::ScopedAStatus toScopedAStatus(const android::base::Result<T, E>& result,
286                                    aidl::android::hardware::automotive::vehicle::StatusCode status,
287                                    const std::string& additionalErrorMsg) {
288     if (result.ok()) {
289         return ndk::ScopedAStatus::ok();
290     }
291     return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
292             toInt(status),
293             fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str());
294 }
295 
296 template <class T, class E>
toScopedAStatus(const android::base::Result<T,E> & result,aidl::android::hardware::automotive::vehicle::StatusCode status)297 ndk::ScopedAStatus toScopedAStatus(
298         const android::base::Result<T, E>& result,
299         aidl::android::hardware::automotive::vehicle::StatusCode status) {
300     return toScopedAStatus(result, status, "");
301 }
302 
303 template <class T>
toScopedAStatus(const VhalResult<T> & result)304 ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result) {
305     return toScopedAStatus(result, getErrorCode(result));
306 }
307 
308 template <class T>
toScopedAStatus(const VhalResult<T> & result,const std::string & additionalErrorMsg)309 ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result,
310                                    const std::string& additionalErrorMsg) {
311     return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
312 }
313 
314 struct PropIdAreaId {
315     int32_t propId;
316     int32_t areaId;
317 
318     inline bool operator==(const PropIdAreaId& other) const {
319         return areaId == other.areaId && propId == other.propId;
320     }
321 };
322 
323 struct PropIdAreaIdHash {
operatorPropIdAreaIdHash324     inline size_t operator()(const PropIdAreaId& propIdAreaId) const {
325         size_t res = 0;
326         hashCombine(res, propIdAreaId.propId);
327         hashCombine(res, propIdAreaId.areaId);
328         return res;
329     }
330 };
331 
332 }  // namespace vehicle
333 }  // namespace automotive
334 }  // namespace hardware
335 }  // namespace android
336 
337 #endif  // android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
338