1 /*
2  * Copyright (C) 2019 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 #define LOG_TAG "ProtoMsgConverter"
18 
19 #include <memory>
20 #include <vector>
21 
22 #include <log/log.h>
23 
24 #include <vhal_v2_0/VehicleUtils.h>
25 
26 #include "ProtoMessageConverter.h"
27 
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace vehicle {
32 namespace V2_0 {
33 
34 namespace impl {
35 
36 namespace proto_msg_converter {
37 
38 // If protobuf class PROTO_VALUE has value in field PROTO_VARNAME,
39 // then casting the value by CAST and copying it to VHAL_TYPE_VALUE->VHAL_TYPE_VARNAME
40 #define CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, \
41                                                   VHAL_TYPE_VARNAME, CAST)                     \
42     if (PROTO_VALUE.has_##PROTO_VARNAME()) {                                                   \
43         (VHAL_TYPE_VALUE)->VHAL_TYPE_VARNAME = CAST(PROTO_VALUE.PROTO_VARNAME());              \
44     }
45 
46 // Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
47 // VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME, every element of PROTO_VECNAME
48 // is casted by CAST
49 #define CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
50                                             VHAL_TYPE_VECNAME, CAST)                     \
51     do {                                                                                 \
52         (VHAL_TYPE_VALUE)->VHAL_TYPE_VECNAME.resize(PROTO_VALUE.PROTO_VECNAME##_size()); \
53         size_t idx = 0;                                                                  \
54         for (auto& value : PROTO_VALUE.PROTO_VECNAME()) {                                \
55             VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME[idx++] = CAST(value);                     \
56         }                                                                                \
57     } while (0)
58 
59 // If protobuf message has value in field PROTO_VARNAME,
60 // then copying it to VHAL_TYPE_VALUE->VHAL_TYPE_VARNAME
61 #define CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, \
62                                              VHAL_TYPE_VARNAME)                           \
63     CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(                                            \
64             PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VARNAME, /*NO CAST*/)
65 
66 // Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
67 // VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME
68 #define COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
69                                        VHAL_TYPE_VECNAME)                           \
70     CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(                                            \
71             PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VECNAME, /*NO CAST*/)
72 
toProto(vhal_proto::VehiclePropConfig * protoCfg,const VehiclePropConfig & cfg)73 void toProto(vhal_proto::VehiclePropConfig* protoCfg, const VehiclePropConfig& cfg) {
74     protoCfg->set_prop(cfg.prop);
75     protoCfg->set_access(toInt(cfg.access));
76     protoCfg->set_change_mode(toInt(cfg.changeMode));
77     protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
78 
79     for (auto& configElement : cfg.configArray) {
80         protoCfg->add_config_array(configElement);
81     }
82 
83     if (cfg.configString.size() > 0) {
84         protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
85     }
86 
87     protoCfg->clear_area_configs();
88     for (auto& areaConfig : cfg.areaConfigs) {
89         auto* protoACfg = protoCfg->add_area_configs();
90         protoACfg->set_area_id(areaConfig.areaId);
91 
92         switch (getPropType(cfg.prop)) {
93             case VehiclePropertyType::STRING:
94             case VehiclePropertyType::BOOLEAN:
95             case VehiclePropertyType::INT32_VEC:
96             case VehiclePropertyType::INT64_VEC:
97             case VehiclePropertyType::FLOAT_VEC:
98             case VehiclePropertyType::BYTES:
99             case VehiclePropertyType::MIXED:
100                 // Do nothing.  These types don't have min/max values
101                 break;
102             case VehiclePropertyType::INT64:
103                 protoACfg->set_min_int64_value(areaConfig.minInt64Value);
104                 protoACfg->set_max_int64_value(areaConfig.maxInt64Value);
105                 break;
106             case VehiclePropertyType::FLOAT:
107                 protoACfg->set_min_float_value(areaConfig.minFloatValue);
108                 protoACfg->set_max_float_value(areaConfig.maxFloatValue);
109                 break;
110             case VehiclePropertyType::INT32:
111                 protoACfg->set_min_int32_value(areaConfig.minInt32Value);
112                 protoACfg->set_max_int32_value(areaConfig.maxInt32Value);
113                 break;
114             default:
115                 ALOGW("%s: Unknown property type:  0x%x", __func__, toInt(getPropType(cfg.prop)));
116                 break;
117         }
118     }
119 
120     protoCfg->set_min_sample_rate(cfg.minSampleRate);
121     protoCfg->set_max_sample_rate(cfg.maxSampleRate);
122 }
123 
fromProto(VehiclePropConfig * cfg,const vhal_proto::VehiclePropConfig & protoCfg)124 void fromProto(VehiclePropConfig* cfg, const vhal_proto::VehiclePropConfig& protoCfg) {
125     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, prop, cfg, prop);
126     CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, access, cfg, access,
127                                               static_cast<VehiclePropertyAccess>);
128     CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, change_mode, cfg, changeMode,
129                                               static_cast<VehiclePropertyChangeMode>);
130     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoCfg, config_array, cfg, configArray);
131     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, config_string, cfg, configString);
132 
133     auto cast_to_acfg = [](const vhal_proto::VehicleAreaConfig& protoAcfg) {
134         VehicleAreaConfig acfg;
135         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, area_id, &acfg, areaId);
136         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_int32_value, &acfg, minInt32Value);
137         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_int32_value, &acfg, maxInt32Value);
138         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_int64_value, &acfg, minInt64Value);
139         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_int64_value, &acfg, maxInt64Value);
140         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_float_value, &acfg, minFloatValue);
141         CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_float_value, &acfg, maxFloatValue);
142         return acfg;
143     };
144 
145     CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoCfg, area_configs, cfg, areaConfigs, cast_to_acfg);
146 
147     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, min_sample_rate, cfg, minSampleRate);
148     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, max_sample_rate, cfg, maxSampleRate);
149 }
150 
toProto(vhal_proto::VehiclePropValue * protoVal,const VehiclePropValue & val)151 void toProto(vhal_proto::VehiclePropValue* protoVal, const VehiclePropValue& val) {
152     protoVal->set_prop(val.prop);
153     protoVal->set_value_type(toInt(getPropType(val.prop)));
154     protoVal->set_timestamp(val.timestamp);
155     protoVal->set_status((vhal_proto::VehiclePropStatus)(val.status));
156     protoVal->set_area_id(val.areaId);
157 
158     // Copy value data if it is set.
159     //  - for bytes and strings, this is indicated by size > 0
160     //  - for int32, int64, and float, copy the values if vectors have data
161     if (val.value.stringValue.size() > 0) {
162         protoVal->set_string_value(val.value.stringValue.c_str(), val.value.stringValue.size());
163     }
164 
165     if (val.value.bytes.size() > 0) {
166         protoVal->set_bytes_value(val.value.bytes.data(), val.value.bytes.size());
167     }
168 
169     for (auto& int32Value : val.value.int32Values) {
170         protoVal->add_int32_values(int32Value);
171     }
172 
173     for (auto& int64Value : val.value.int64Values) {
174         protoVal->add_int64_values(int64Value);
175     }
176 
177     for (auto& floatValue : val.value.floatValues) {
178         protoVal->add_float_values(floatValue);
179     }
180 }
181 
fromProto(VehiclePropValue * val,const vhal_proto::VehiclePropValue & protoVal)182 void fromProto(VehiclePropValue* val, const vhal_proto::VehiclePropValue& protoVal) {
183     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, prop, val, prop);
184     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, timestamp, val, timestamp);
185     CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, status, val, status,
186                                               static_cast<VehiclePropertyStatus>);
187     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, area_id, val, areaId);
188 
189     // Copy value data
190     CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, string_value, val, value.stringValue);
191 
192     auto cast_proto_bytes_to_vec = [](auto&& bytes) {
193         return std::vector<uint8_t>(bytes.begin(), bytes.end());
194     };
195     CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, bytes_value, val, value.bytes,
196                                               cast_proto_bytes_to_vec);
197 
198     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, int32_values, val, value.int32Values);
199     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, int64_values, val, value.int64Values);
200     COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, float_values, val, value.floatValues);
201 }
202 
203 #undef COPY_PROTOBUF_VEC_TO_VHAL_TYPE
204 #undef CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE
205 #undef CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE
206 #undef CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE
207 
208 }  // namespace proto_msg_converter
209 
210 }  // namespace impl
211 
212 }  // namespace V2_0
213 }  // namespace vehicle
214 }  // namespace automotive
215 }  // namespace hardware
216 }  // namespace android
217