1 /*
2 * Copyright 2016 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 #include "VtsCompilerUtils.h"
18
19 #include <limits.h>
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include <cstdint>
26 #include <fstream>
27 #include <iostream>
28 #include <sstream>
29
30 #include <google/protobuf/text_format.h>
31
32 #include "specification_parser/InterfaceSpecificationParser.h"
33 #include "utils/InterfaceSpecUtil.h"
34 #include "utils/StringUtil.h"
35
36 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
37
38 using namespace std;
39
40 namespace android {
41 namespace vts {
42
ComponentClassToString(int component_class)43 string ComponentClassToString(int component_class) {
44 switch (component_class) {
45 case UNKNOWN_CLASS:
46 return "unknown_class";
47 case HAL_CONVENTIONAL:
48 return "hal_conventional";
49 case HAL_CONVENTIONAL_SUBMODULE:
50 return "hal_conventional_submodule";
51 case HAL_HIDL:
52 return "hal_hidl";
53 case HAL_HIDL_WRAPPED_CONVENTIONAL:
54 return "hal_hidl_wrapped_conventional";
55 case LIB_SHARED:
56 return "lib_shared";
57 }
58 cerr << "error: invalid component_class " << component_class << endl;
59 exit(-1);
60 }
61
ComponentTypeToString(int component_type)62 string ComponentTypeToString(int component_type) {
63 switch (component_type) {
64 case UNKNOWN_TYPE:
65 return "unknown_type";
66 case AUDIO:
67 return "audio";
68 case CAMERA:
69 return "camera";
70 case GPS:
71 return "gps";
72 case LIGHT:
73 return "light";
74 case WIFI:
75 return "wifi";
76 case MOBILE:
77 return "mobile";
78 case BLUETOOTH:
79 return "bluetooth";
80 case TV_INPUT:
81 return "tv_input";
82 case NFC:
83 return "nfc";
84 case VEHICLE:
85 return "vehicle";
86 case VIBRATOR:
87 return "vibrator";
88 case THERMAL:
89 return "thermal";
90 case CONTEXTHUB:
91 return "contexthub";
92 case SENSORS:
93 return "sensors";
94 case VR:
95 return "vr";
96 case GRAPHICS_ALLOCATOR:
97 return "graphics_allocator";
98 case GRAPHICS_MAPPER:
99 return "graphics_mapper";
100 case GRAPHICS_COMPOSER:
101 return "graphics_composer";
102 case BIONIC_LIBM:
103 return "bionic_libm";
104 case TV_CEC:
105 return "tv_cec";
106 case RADIO:
107 return "radio";
108 case MEDIA_OMX:
109 return "media_omx";
110 }
111 cerr << "error: invalid component_type " << component_type << endl;
112 exit(-1);
113 }
114
GetCppVariableType(const std::string scalar_type_string)115 string GetCppVariableType(const std::string scalar_type_string) {
116 if (scalar_type_string == "void" ||
117 scalar_type_string == "int32_t" || scalar_type_string == "uint32_t" ||
118 scalar_type_string == "int8_t" || scalar_type_string == "uint8_t" ||
119 scalar_type_string == "int64_t" || scalar_type_string == "uint64_t" ||
120 scalar_type_string == "int16_t" || scalar_type_string == "uint16_t") {
121 return scalar_type_string;
122 } else if (scalar_type_string == "bool_t") {
123 return "bool";
124 } else if (scalar_type_string == "float_t") {
125 return "float";
126 } else if (scalar_type_string == "double_t") {
127 return "double";
128 } else if (scalar_type_string == "ufloat") {
129 return "unsigned float";
130 } else if (scalar_type_string == "udouble") {
131 return "unsigned double";
132 } else if (scalar_type_string == "string") {
133 return "std::string";
134 } else if (scalar_type_string == "pointer") {
135 return "void*";
136 } else if (scalar_type_string == "char_pointer") {
137 return "char*";
138 } else if (scalar_type_string == "uchar_pointer") {
139 return "unsigned char*";
140 } else if (scalar_type_string == "void_pointer") {
141 return "void*";
142 } else if (scalar_type_string == "function_pointer") {
143 return "void*";
144 }
145
146 cerr << __func__ << ":" << __LINE__ << " "
147 << "error: unknown scalar_type " << scalar_type_string << endl;
148 exit(-1);
149 }
150
GetCppVariableType(const VariableSpecificationMessage & arg,const ComponentSpecificationMessage * message,bool generate_const,int var_depth)151 string GetCppVariableType(const VariableSpecificationMessage& arg,
152 const ComponentSpecificationMessage* message,
153 bool generate_const,
154 int var_depth) {
155 string result;
156 switch (arg.type()) {
157 case TYPE_VOID:
158 {
159 return "void";
160 }
161 case TYPE_PREDEFINED:
162 {
163 result = arg.predefined_type();
164 break;
165 }
166 case TYPE_SCALAR:
167 {
168 result = GetCppVariableType(arg.scalar_type());
169 break;
170 }
171 case TYPE_STRING:
172 {
173 result = "::android::hardware::hidl_string";
174 break;
175 }
176 case TYPE_ENUM:
177 {
178 if (!arg.has_enum_value() && arg.has_predefined_type()) {
179 result = arg.predefined_type();
180 } else if (arg.has_enum_value() && arg.has_name()) {
181 result = arg.name(); // nested enum type.
182 } else {
183 cerr << __func__ << ":" << __LINE__
184 << " ERROR no predefined_type set for enum variable" << endl;
185 exit(-1);
186 }
187 break;
188 }
189 case TYPE_VECTOR:
190 {
191 string element_type = GetCppVariableType(arg.vector_value(0), message);
192 if (generate_const && arg.vector_value(0).type() == TYPE_REF) {
193 result = "::android::hardware::hidl_vec<const " + element_type + ">";
194 } else {
195 result = "::android::hardware::hidl_vec<" + element_type + ">";
196 }
197 break;
198 }
199 case TYPE_ARRAY:
200 {
201 string element_type;
202 if (arg.vector_value(0).type() != TYPE_ARRAY) {
203 element_type = GetCppVariableType(arg.vector_value(0), message);
204 result = "::android::hardware::hidl_array<" + element_type + ","
205 + to_string(arg.vector_size()) + ">";
206 } else {
207 element_type = GetCppVariableType(arg.vector_value(0), message);
208 string prefix = element_type.substr(0, element_type.find(",") + 1);
209 string suffix = element_type.substr(element_type.find(","));
210 result = prefix + " " + to_string(arg.vector_size()) + suffix;
211 }
212 break;
213 }
214 case TYPE_STRUCT:
215 {
216 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) {
217 result = arg.predefined_type();
218 } else if (arg.has_struct_type()) {
219 result = arg.struct_type();
220 } else if (arg.sub_struct_size() > 0 || arg.struct_value_size() > 0) {
221 result = arg.name();
222 } else {
223 cerr << __func__ << ":" << __LINE__ << " ERROR"
224 << " no predefined_type, struct_type, nor sub_struct set"
225 << " for struct variable"
226 << " (arg name " << arg.name() << ")" << endl;
227 exit(-1);
228 }
229 break;
230 }
231 case TYPE_UNION:
232 {
233 if (arg.union_value_size() == 0 && arg.has_predefined_type()) {
234 result = arg.predefined_type();
235 } else if (arg.has_union_type()) {
236 result = arg.union_type();
237 } else {
238 cerr << __func__ << ":" << __LINE__
239 << " ERROR no predefined_type or union_type set for union"
240 << " variable" << endl;
241 exit(-1);
242 }
243 break;
244 }
245 case TYPE_HIDL_CALLBACK:
246 {
247 if (arg.has_predefined_type()) {
248 result = "sp<" + arg.predefined_type() + ">";
249 } else {
250 cerr << __func__ << ":" << __LINE__
251 << " ERROR no predefined_type set for hidl callback variable"
252 << endl;
253 exit(-1);
254 }
255 break;
256 }
257 case TYPE_HANDLE:
258 {
259 result = "::android::hardware::hidl_handle";
260 break;
261 }
262 case TYPE_HIDL_INTERFACE:
263 {
264 if (arg.has_predefined_type()) {
265 result = "sp<" + arg.predefined_type() + ">";
266 } else {
267 cerr << __func__ << ":" << __LINE__
268 << " ERROR no predefined_type set for hidl interface variable"
269 << endl;
270 exit(-1);
271 }
272 break;
273 }
274 case TYPE_MASK:
275 {
276 result = GetCppVariableType(arg.scalar_type());
277 break;
278 }
279 case TYPE_HIDL_MEMORY:
280 {
281 result = "::android::hardware::hidl_memory";
282 break;
283 }
284 case TYPE_POINTER:
285 {
286 result = "void*";
287 if (generate_const) {
288 return "const " + result;
289 }
290 return result;
291 }
292 case TYPE_FMQ_SYNC:
293 {
294 string element_type = GetCppVariableType(arg.fmq_value(0), message);
295 result = "::android::hardware::MQDescriptorSync<" + element_type + ">";
296 break;
297 }
298 case TYPE_FMQ_UNSYNC:
299 {
300 string element_type = GetCppVariableType(arg.fmq_value(0), message);
301 result = "::android::hardware::MQDescriptorUnsync<" + element_type + ">";
302 break;
303 }
304 case TYPE_REF:
305 {
306 string element_type = GetCppVariableType(arg.ref_value(), message,
307 false, var_depth + 1);
308 if (element_type.length() > 0) {
309 if (var_depth == 0) {
310 return "const " + element_type + " *";
311 } else {
312 return element_type + " *const";
313 }
314 }
315 cerr << __func__ << ":" << __LINE__ << " ERROR"
316 << " TYPE_REF malformed" << endl;
317 exit(-1);
318 }
319 default:
320 {
321 cerr << __func__ << ":" << __LINE__ << " " << ": type " << arg.type()
322 << " not supported" << endl;
323 exit(-1);
324 }
325 }
326 if (generate_const) {
327 return "const " + result + "&";
328 }
329 return result;
330 }
331
GetConversionToProtobufFunctionName(VariableSpecificationMessage arg)332 string GetConversionToProtobufFunctionName(VariableSpecificationMessage arg) {
333 if (arg.type() == TYPE_PREDEFINED) {
334 if (arg.predefined_type() == "camera_info_t*") {
335 return "ConvertCameraInfoToProtobuf";
336 } else if (arg.predefined_type() == "hw_device_t**") {
337 return "";
338 } else {
339 cerr << __FILE__ << ":" << __LINE__ << " "
340 << "error: unknown instance type " << arg.predefined_type() << endl;
341 }
342 }
343 cerr << __FUNCTION__ << ": non-supported type " << arg.type() << endl;
344 exit(-1);
345 }
346
GetCppInstanceType(const VariableSpecificationMessage & arg,const string & msg,const ComponentSpecificationMessage * message)347 string GetCppInstanceType(
348 const VariableSpecificationMessage& arg,
349 const string& msg,
350 const ComponentSpecificationMessage* message) {
351 switch(arg.type()) {
352 case TYPE_PREDEFINED: {
353 if (arg.predefined_type() == "struct light_state_t*") {
354 if (msg.length() == 0) {
355 return "GenerateLightState()";
356 } else {
357 return "GenerateLightStateUsingMessage(" + msg + ")";
358 }
359 } else if (arg.predefined_type() == "GpsCallbacks*") {
360 return "GenerateGpsCallbacks()";
361 } else if (arg.predefined_type() == "GpsUtcTime") {
362 return "GenerateGpsUtcTime()";
363 } else if (arg.predefined_type() == "vts_gps_latitude") {
364 return "GenerateLatitude()";
365 } else if (arg.predefined_type() == "vts_gps_longitude") {
366 return "GenerateLongitude()";
367 } else if (arg.predefined_type() == "vts_gps_accuracy") {
368 return "GenerateGpsAccuracy()";
369 } else if (arg.predefined_type() == "vts_gps_flags_uint16") {
370 return "GenerateGpsFlagsUint16()";
371 } else if (arg.predefined_type() == "GpsPositionMode") {
372 return "GenerateGpsPositionMode()";
373 } else if (arg.predefined_type() == "GpsPositionRecurrence") {
374 return "GenerateGpsPositionRecurrence()";
375 } else if (arg.predefined_type() == "hw_module_t*") {
376 return "(hw_module_t*) malloc(sizeof(hw_module_t))";
377 } else if (arg.predefined_type() == "hw_module_t**") {
378 return "(hw_module_t**) malloc(sizeof(hw_module_t*))";
379 } else if (arg.predefined_type() == "hw_device_t**") {
380 return "(hw_device_t**) malloc(sizeof(hw_device_t*))";
381 } else if (arg.predefined_type() == "camera_info_t*") {
382 if (msg.length() == 0) {
383 return "GenerateCameraInfo()";
384 } else {
385 return "GenerateCameraInfoUsingMessage(" + msg + ")";
386 }
387 } else if (arg.predefined_type() == "camera_module_callbacks_t*") {
388 return "GenerateCameraModuleCallbacks()";
389 } else if (arg.predefined_type() == "camera_notify_callback") {
390 return "GenerateCameraNotifyCallback()";
391 } else if (arg.predefined_type() == "camera_data_callback") {
392 return "GenerateCameraDataCallback()";
393 } else if (arg.predefined_type() == "camera_data_timestamp_callback") {
394 return "GenerateCameraDataTimestampCallback()";
395 } else if (arg.predefined_type() == "camera_request_memory") {
396 return "GenerateCameraRequestMemory()";
397 } else if (arg.predefined_type() == "wifi_handle*") {
398 return "(wifi_handle*) malloc(sizeof(wifi_handle))";
399 } else if (arg.predefined_type() == "struct camera_device*") {
400 return "(struct camera_device*) malloc(sizeof(struct camera_device))";
401 } else if (arg.predefined_type() == "struct preview_stream_ops*") {
402 return "(preview_stream_ops*) malloc(sizeof(preview_stream_ops))";
403 } else if (endsWith(arg.predefined_type(), "*")) {
404 // known use cases: bt_callbacks_t
405 return "(" + arg.predefined_type() + ") malloc(sizeof("
406 + arg.predefined_type().substr(0, arg.predefined_type().size() - 1)
407 + "))";
408 } else {
409 cerr << __func__ << ":" << __LINE__ << " "
410 << "error: unknown instance type " << arg.predefined_type() << endl;
411 }
412 break;
413 }
414 case TYPE_SCALAR: {
415 if (arg.scalar_type() == "bool_t") {
416 return "RandomBool()";
417 } else if (arg.scalar_type() == "uint32_t") {
418 return "RandomUint32()";
419 } else if (arg.scalar_type() == "int32_t") {
420 return "RandomInt32()";
421 } else if (arg.scalar_type() == "uint64_t") {
422 return "RandomUint64()";
423 } else if (arg.scalar_type() == "int64_t") {
424 return "RandomInt64()";
425 } else if (arg.scalar_type() == "uint16_t") {
426 return "RandomUint16()";
427 } else if (arg.scalar_type() == "int16_t") {
428 return "RandomInt16()";
429 } else if (arg.scalar_type() == "uint8_t") {
430 return "RandomUint8()";
431 } else if (arg.scalar_type() == "int8_t") {
432 return "RandomInt8()";
433 } else if (arg.scalar_type() == "float_t") {
434 return "RandomFloat()";
435 } else if (arg.scalar_type() == "double_t") {
436 return "RandomDouble()";
437 } else if (arg.scalar_type() == "char_pointer") {
438 return "RandomCharPointer()";
439 } else if (arg.scalar_type() == "uchar_pointer") {
440 return "(unsigned char*) RandomCharPointer()";
441 } else if (arg.scalar_type() == "pointer" ||
442 arg.scalar_type() == "void_pointer") {
443 return "RandomVoidPointer()";
444 }
445 cerr << __FILE__ << ":" << __LINE__ << " "
446 << "error: unsupported scalar data type " << arg.scalar_type() << endl;
447 exit(-1);
448 }
449 case TYPE_ENUM:
450 case TYPE_MASK: {
451 if (!arg.has_enum_value() && arg.has_predefined_type()) {
452 if (!message || message->component_class() != HAL_HIDL) {
453 return "(" + arg.predefined_type() + ") RandomUint32()";
454 } else {
455 std::string predefined_type_name = arg.predefined_type();
456 ReplaceSubString(predefined_type_name, "::", "__");
457 return "Random" + predefined_type_name + "()";
458 // TODO: generate a function which can dynamically choose the value.
459 /* for (const auto& attribute : message->attribute()) {
460 if (attribute.type() == TYPE_ENUM &&
461 attribute.name() == arg.predefined_type()) {
462 // TODO: pick at runtime
463 return message->component_name() + "::"
464 + arg.predefined_type() + "::"
465 + attribute.enum_value().enumerator(0);
466 }
467 } */
468 }
469 } else {
470 cerr << __func__
471 << " ENUM either has enum value or doesn't have predefined type"
472 << endl;
473 exit(-1);
474 }
475 break;
476 }
477 case TYPE_STRING: {
478 return "android::hardware::hidl_string(RandomCharPointer())";
479 }
480 case TYPE_STRUCT: {
481 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) {
482 return message->component_name() + "::" + arg.predefined_type() + "()";
483 }
484 break;
485 }
486 case TYPE_VECTOR: { // only for HAL_HIDL
487 // TODO: generate code that initializes a local hidl_vec.
488 return "";
489 }
490 case TYPE_HIDL_CALLBACK: {
491 return arg.predefined_type() + "()";
492 }
493 default:
494 break;
495 }
496 cerr << __func__ << ": error: unsupported type " << arg.type() << endl;
497 exit(-1);
498 }
499
vts_fs_mkdirs(char * file_path,mode_t mode)500 int vts_fs_mkdirs(char* file_path, mode_t mode) {
501 char* p;
502
503 for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
504 *p = '\0';
505 if (mkdir(file_path, mode) == -1) {
506 if (errno != EEXIST) {
507 *p = '/';
508 return -1;
509 }
510 }
511 *p = '/';
512 }
513 return 0;
514 }
515
ClearStringWithNameSpaceAccess(const string & str)516 string ClearStringWithNameSpaceAccess(const string& str) {
517 string result = str;
518 ReplaceSubString(result, "::", "__");
519 return result;
520 }
521
522 // Returns a string which joins the given dir_path and file_name.
PathJoin(const char * dir_path,const char * file_name)523 string PathJoin(const char* dir_path, const char* file_name) {
524 string result;
525 if (dir_path) {
526 result = dir_path;
527 if (!file_name) return result;
528 } else if (!file_name) return result;
529
530 if (file_name[0] != '.') {
531 if (result.c_str()[result.length()-1] != '/') {
532 result += "/";
533 }
534 }
535 result += file_name;
536 return result;
537 }
538
539 // Returns a string which remove given base_path from file_path if included.
RemoveBaseDir(const string & file_path,const string & base_path)540 string RemoveBaseDir(const string& file_path, const string& base_path) {
541 if (strncmp(file_path.c_str(), base_path.c_str(), base_path.length())) {
542 return file_path;
543 }
544 string result;
545 result = &file_path.c_str()[base_path.length()];
546 if (result.c_str()[0] == '/') {
547 result = &result.c_str()[1];
548 }
549 return result;
550 }
551
GetComponentName(const ComponentSpecificationMessage & message)552 string GetComponentName(const ComponentSpecificationMessage& message) {
553 if (!message.component_name().empty()) {
554 return message.component_name();
555 }
556
557 string component_name = message.original_data_structure_name();
558 while (!component_name.empty()
559 && (std::isspace(component_name.back()) || component_name.back() == '*')) {
560 component_name.pop_back();
561 }
562 const auto pos = component_name.find_last_of(" ");
563 if (pos != std::string::npos) {
564 component_name = component_name.substr(pos + 1);
565 }
566 return component_name;
567 }
568
GetFQName(const ComponentSpecificationMessage & message)569 FQName GetFQName(const ComponentSpecificationMessage& message) {
570 return FQName(message.package(),
571 GetVersionString(message.component_type_version()),
572 GetComponentName(message));
573 }
574
575 } // namespace vts
576 } // namespace android
577