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