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,const ComponentSpecificationMessage * message,bool generate_const,int var_depth)156 string GetCppVariableType(const VariableSpecificationMessage& arg,
157 const ComponentSpecificationMessage* message,
158 bool generate_const,
159 int var_depth) {
160 string result;
161 switch (arg.type()) {
162 case TYPE_VOID:
163 {
164 return "void";
165 }
166 case TYPE_PREDEFINED:
167 {
168 result = arg.predefined_type();
169 break;
170 }
171 case TYPE_SCALAR:
172 {
173 result = GetCppVariableType(arg.scalar_type());
174 break;
175 }
176 case TYPE_STRING:
177 {
178 result = "::android::hardware::hidl_string";
179 break;
180 }
181 case TYPE_ENUM:
182 {
183 if (!arg.has_enum_value() && arg.has_predefined_type()) {
184 result = arg.predefined_type();
185 } else if (arg.has_enum_value() && arg.has_name()) {
186 result = arg.name(); // nested enum type.
187 } else {
188 cerr << __func__ << ":" << __LINE__
189 << " ERROR no predefined_type set for enum variable" << endl;
190 exit(-1);
191 }
192 break;
193 }
194 case TYPE_VECTOR:
195 {
196 string element_type = GetCppVariableType(arg.vector_value(0), message);
197 if (generate_const && arg.vector_value(0).type() == TYPE_REF) {
198 result = "::android::hardware::hidl_vec<const " + element_type + ">";
199 } else {
200 result = "::android::hardware::hidl_vec<" + element_type + ">";
201 }
202 break;
203 }
204 case TYPE_ARRAY:
205 {
206 string element_type;
207 if (arg.vector_value(0).type() != TYPE_ARRAY) {
208 element_type = GetCppVariableType(arg.vector_value(0), message);
209 result = "::android::hardware::hidl_array<" + element_type + ","
210 + to_string(arg.vector_size()) + ">";
211 } else {
212 element_type = GetCppVariableType(arg.vector_value(0), message);
213 string prefix = element_type.substr(0, element_type.find(",") + 1);
214 string suffix = element_type.substr(element_type.find(","));
215 result = prefix + " " + to_string(arg.vector_size()) + suffix;
216 }
217 break;
218 }
219 case TYPE_STRUCT:
220 {
221 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) {
222 result = arg.predefined_type();
223 } else if (arg.has_struct_type()) {
224 result = arg.struct_type();
225 } else if (arg.sub_struct_size() > 0 || arg.struct_value_size() > 0) {
226 result = arg.name();
227 } else {
228 cerr << __func__ << ":" << __LINE__ << " ERROR"
229 << " no predefined_type, struct_type, nor sub_struct set"
230 << " for struct variable"
231 << " (arg name " << arg.name() << ")" << endl;
232 exit(-1);
233 }
234 break;
235 }
236 case TYPE_UNION:
237 {
238 if (arg.union_value_size() == 0 && arg.has_predefined_type()) {
239 result = arg.predefined_type();
240 } else if (arg.has_union_type()) {
241 result = arg.union_type();
242 } else {
243 cerr << __func__ << ":" << __LINE__
244 << " ERROR no predefined_type or union_type set for union"
245 << " variable" << endl;
246 exit(-1);
247 }
248 break;
249 }
250 case TYPE_HIDL_CALLBACK:
251 {
252 if (arg.has_predefined_type()) {
253 result = "sp<" + arg.predefined_type() + ">";
254 } else {
255 cerr << __func__ << ":" << __LINE__
256 << " ERROR no predefined_type set for hidl callback variable"
257 << endl;
258 exit(-1);
259 }
260 break;
261 }
262 case TYPE_HANDLE:
263 {
264 result = "::android::hardware::hidl_handle";
265 break;
266 }
267 case TYPE_HIDL_INTERFACE:
268 {
269 if (arg.has_predefined_type()) {
270 result = "sp<" + arg.predefined_type() + ">";
271 } else {
272 cerr << __func__ << ":" << __LINE__
273 << " ERROR no predefined_type set for hidl interface variable"
274 << endl;
275 exit(-1);
276 }
277 break;
278 }
279 case TYPE_MASK:
280 {
281 result = GetCppVariableType(arg.scalar_type());
282 break;
283 }
284 case TYPE_HIDL_MEMORY:
285 {
286 result = "::android::hardware::hidl_memory";
287 break;
288 }
289 case TYPE_POINTER:
290 {
291 result = "void*";
292 if (generate_const) {
293 return "const " + result;
294 }
295 return result;
296 }
297 case TYPE_FMQ_SYNC:
298 {
299 string element_type = GetCppVariableType(arg.fmq_value(0), message);
300 result = "::android::hardware::MQDescriptorSync<" + element_type + ">";
301 break;
302 }
303 case TYPE_FMQ_UNSYNC:
304 {
305 string element_type = GetCppVariableType(arg.fmq_value(0), message);
306 result = "::android::hardware::MQDescriptorUnsync<" + element_type + ">";
307 break;
308 }
309 case TYPE_REF:
310 {
311 string element_type = GetCppVariableType(arg.ref_value(), message,
312 false, var_depth + 1);
313 if (element_type.length() > 0) {
314 if (var_depth == 0) {
315 return "const " + element_type + " *";
316 } else {
317 return element_type + " *const";
318 }
319 }
320 cerr << __func__ << ":" << __LINE__ << " ERROR"
321 << " TYPE_REF malformed" << endl;
322 exit(-1);
323 }
324 default:
325 {
326 cerr << __func__ << ":" << __LINE__ << " " << ": type " << arg.type()
327 << " not supported" << endl;
328 exit(-1);
329 }
330 }
331 if (generate_const) {
332 return "const " + result + "&";
333 }
334 return result;
335 }
336
GetConversionToProtobufFunctionName(VariableSpecificationMessage arg)337 string GetConversionToProtobufFunctionName(VariableSpecificationMessage arg) {
338 if (arg.type() == TYPE_PREDEFINED) {
339 if (arg.predefined_type() == "camera_info_t*") {
340 return "ConvertCameraInfoToProtobuf";
341 } else if (arg.predefined_type() == "hw_device_t**") {
342 return "";
343 } else {
344 cerr << __FILE__ << ":" << __LINE__ << " "
345 << "error: unknown instance type " << arg.predefined_type() << endl;
346 }
347 }
348 cerr << __FUNCTION__ << ": non-supported type " << arg.type() << endl;
349 exit(-1);
350 }
351
GetCppInstanceType(const VariableSpecificationMessage & arg,const string & msg,const ComponentSpecificationMessage * message)352 string GetCppInstanceType(
353 const VariableSpecificationMessage& arg,
354 const string& msg,
355 const ComponentSpecificationMessage* message) {
356 switch(arg.type()) {
357 case TYPE_PREDEFINED: {
358 if (arg.predefined_type() == "struct light_state_t*") {
359 if (msg.length() == 0) {
360 return "GenerateLightState()";
361 } else {
362 return "GenerateLightStateUsingMessage(" + msg + ")";
363 }
364 } else if (arg.predefined_type() == "GpsCallbacks*") {
365 return "GenerateGpsCallbacks()";
366 } else if (arg.predefined_type() == "GpsUtcTime") {
367 return "GenerateGpsUtcTime()";
368 } else if (arg.predefined_type() == "vts_gps_latitude") {
369 return "GenerateLatitude()";
370 } else if (arg.predefined_type() == "vts_gps_longitude") {
371 return "GenerateLongitude()";
372 } else if (arg.predefined_type() == "vts_gps_accuracy") {
373 return "GenerateGpsAccuracy()";
374 } else if (arg.predefined_type() == "vts_gps_flags_uint16") {
375 return "GenerateGpsFlagsUint16()";
376 } else if (arg.predefined_type() == "GpsPositionMode") {
377 return "GenerateGpsPositionMode()";
378 } else if (arg.predefined_type() == "GpsPositionRecurrence") {
379 return "GenerateGpsPositionRecurrence()";
380 } else if (arg.predefined_type() == "hw_module_t*") {
381 return "(hw_module_t*) malloc(sizeof(hw_module_t))";
382 } else if (arg.predefined_type() == "hw_module_t**") {
383 return "(hw_module_t**) malloc(sizeof(hw_module_t*))";
384 } else if (arg.predefined_type() == "hw_device_t**") {
385 return "(hw_device_t**) malloc(sizeof(hw_device_t*))";
386 } else if (arg.predefined_type() == "camera_info_t*") {
387 if (msg.length() == 0) {
388 return "GenerateCameraInfo()";
389 } else {
390 return "GenerateCameraInfoUsingMessage(" + msg + ")";
391 }
392 } else if (arg.predefined_type() == "camera_module_callbacks_t*") {
393 return "GenerateCameraModuleCallbacks()";
394 } else if (arg.predefined_type() == "camera_notify_callback") {
395 return "GenerateCameraNotifyCallback()";
396 } else if (arg.predefined_type() == "camera_data_callback") {
397 return "GenerateCameraDataCallback()";
398 } else if (arg.predefined_type() == "camera_data_timestamp_callback") {
399 return "GenerateCameraDataTimestampCallback()";
400 } else if (arg.predefined_type() == "camera_request_memory") {
401 return "GenerateCameraRequestMemory()";
402 } else if (arg.predefined_type() == "wifi_handle*") {
403 return "(wifi_handle*) malloc(sizeof(wifi_handle))";
404 } else if (arg.predefined_type() == "struct camera_device*") {
405 return "(struct camera_device*) malloc(sizeof(struct camera_device))";
406 } else if (arg.predefined_type() == "struct preview_stream_ops*") {
407 return "(preview_stream_ops*) malloc(sizeof(preview_stream_ops))";
408 } else if (endsWith(arg.predefined_type(), "*")) {
409 // known use cases: bt_callbacks_t
410 return "(" + arg.predefined_type() + ") malloc(sizeof("
411 + arg.predefined_type().substr(0, arg.predefined_type().size() - 1)
412 + "))";
413 } else {
414 cerr << __func__ << ":" << __LINE__ << " "
415 << "error: unknown instance type " << arg.predefined_type() << endl;
416 }
417 break;
418 }
419 case TYPE_SCALAR: {
420 if (arg.scalar_type() == "bool_t") {
421 return "RandomBool()";
422 } else if (arg.scalar_type() == "uint32_t") {
423 return "RandomUint32()";
424 } else if (arg.scalar_type() == "int32_t") {
425 return "RandomInt32()";
426 } else if (arg.scalar_type() == "uint64_t") {
427 return "RandomUint64()";
428 } else if (arg.scalar_type() == "int64_t") {
429 return "RandomInt64()";
430 } else if (arg.scalar_type() == "uint16_t") {
431 return "RandomUint16()";
432 } else if (arg.scalar_type() == "int16_t") {
433 return "RandomInt16()";
434 } else if (arg.scalar_type() == "uint8_t") {
435 return "RandomUint8()";
436 } else if (arg.scalar_type() == "int8_t") {
437 return "RandomInt8()";
438 } else if (arg.scalar_type() == "float_t") {
439 return "RandomFloat()";
440 } else if (arg.scalar_type() == "double_t") {
441 return "RandomDouble()";
442 } else if (arg.scalar_type() == "char_pointer") {
443 return "RandomCharPointer()";
444 } else if (arg.scalar_type() == "uchar_pointer") {
445 return "(unsigned char*) RandomCharPointer()";
446 } else if (arg.scalar_type() == "pointer" ||
447 arg.scalar_type() == "void_pointer") {
448 return "RandomVoidPointer()";
449 }
450 cerr << __FILE__ << ":" << __LINE__ << " "
451 << "error: unsupported scalar data type " << arg.scalar_type() << endl;
452 exit(-1);
453 }
454 case TYPE_ENUM:
455 case TYPE_MASK: {
456 if (!arg.has_enum_value() && arg.has_predefined_type()) {
457 if (!message || message->component_class() != HAL_HIDL) {
458 return "(" + arg.predefined_type() + ") RandomUint32()";
459 } else {
460 std::string predefined_type_name = arg.predefined_type();
461 ReplaceSubString(predefined_type_name, "::", "__");
462 return "Random" + predefined_type_name + "()";
463 // TODO: generate a function which can dynamically choose the value.
464 /* for (const auto& attribute : message->attribute()) {
465 if (attribute.type() == TYPE_ENUM &&
466 attribute.name() == arg.predefined_type()) {
467 // TODO: pick at runtime
468 return message->component_name() + "::"
469 + arg.predefined_type() + "::"
470 + attribute.enum_value().enumerator(0);
471 }
472 } */
473 }
474 } else {
475 cerr << __func__
476 << " ENUM either has enum value or doesn't have predefined type"
477 << endl;
478 exit(-1);
479 }
480 break;
481 }
482 case TYPE_STRING: {
483 return "android::hardware::hidl_string(RandomCharPointer())";
484 }
485 case TYPE_STRUCT: {
486 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) {
487 return message->component_name() + "::" + arg.predefined_type() + "()";
488 }
489 break;
490 }
491 case TYPE_VECTOR: { // only for HAL_HIDL
492 // TODO: generate code that initializes a local hidl_vec.
493 return "";
494 }
495 case TYPE_HIDL_CALLBACK: {
496 return arg.predefined_type() + "()";
497 }
498 default:
499 break;
500 }
501 cerr << __func__ << ": error: unsupported type " << arg.type() << endl;
502 exit(-1);
503 }
504
vts_fs_mkdirs(char * file_path,mode_t mode)505 int vts_fs_mkdirs(char* file_path, mode_t mode) {
506 char* p;
507
508 for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
509 *p = '\0';
510 if (mkdir(file_path, mode) == -1) {
511 if (errno != EEXIST) {
512 *p = '/';
513 return -1;
514 }
515 }
516 *p = '/';
517 }
518 return 0;
519 }
520
ClearStringWithNameSpaceAccess(const string & str)521 string ClearStringWithNameSpaceAccess(const string& str) {
522 string result = str;
523 ReplaceSubString(result, "::", "__");
524 return result;
525 }
526
527 // Returns a string which joins the given dir_path and file_name.
PathJoin(const char * dir_path,const char * file_name)528 string PathJoin(const char* dir_path, const char* file_name) {
529 string result;
530 if (dir_path) {
531 result = dir_path;
532 if (!file_name) return result;
533 } else if (!file_name) return result;
534
535 if (file_name[0] != '.') {
536 if (result.c_str()[result.length()-1] != '/') {
537 result += "/";
538 }
539 }
540 result += file_name;
541 return result;
542 }
543
544 // Returns a string which remove given base_path from file_path if included.
RemoveBaseDir(const string & file_path,const string & base_path)545 string RemoveBaseDir(const string& file_path, const string& base_path) {
546 if (strncmp(file_path.c_str(), base_path.c_str(), base_path.length())) {
547 return file_path;
548 }
549 string result;
550 result = &file_path.c_str()[base_path.length()];
551 if (result.c_str()[0] == '/') {
552 result = &result.c_str()[1];
553 }
554 return result;
555 }
556
GetPackageName(const ComponentSpecificationMessage & message)557 string GetPackageName(const ComponentSpecificationMessage& message) {
558 if (!message.package().empty()) {
559 return message.package();
560 }
561 return "";
562 }
563
GetPackagePath(const ComponentSpecificationMessage & message)564 string GetPackagePath(const ComponentSpecificationMessage& message) {
565 string package_path = GetPackageName(message);
566 ReplaceSubString(package_path, ".", "/");
567 return package_path;
568 }
569
GetPackageNamespaceToken(const ComponentSpecificationMessage & message)570 string GetPackageNamespaceToken(const ComponentSpecificationMessage& message) {
571 string package_token = GetPackageName(message);
572 ReplaceSubString(package_token, ".", "::");
573 return package_token;
574 }
575
GetVersion(const ComponentSpecificationMessage & message,bool for_macro)576 string GetVersion(const ComponentSpecificationMessage& message,
577 bool for_macro) {
578 return GetVersionString(message.component_type_version(), for_macro);
579 }
580
GetComponentBaseName(const ComponentSpecificationMessage & message)581 string GetComponentBaseName(const ComponentSpecificationMessage& message) {
582 if (!message.component_name().empty()) {
583 return (message.component_name() == "types"
584 ? "types"
585 : message.component_name().substr(1));
586 } else
587 return GetComponentName(message);
588 }
589
GetComponentName(const ComponentSpecificationMessage & message)590 string GetComponentName(const ComponentSpecificationMessage& message) {
591 if (!message.component_name().empty()) {
592 return message.component_name();
593 }
594
595 string component_name = message.original_data_structure_name();
596 while (!component_name.empty()
597 && (std::isspace(component_name.back()) || component_name.back() == '*')) {
598 component_name.pop_back();
599 }
600 const auto pos = component_name.find_last_of(" ");
601 if (pos != std::string::npos) {
602 component_name = component_name.substr(pos + 1);
603 }
604 return component_name;
605 }
606
GetFQName(const ComponentSpecificationMessage & message)607 FQName GetFQName(const ComponentSpecificationMessage& message) {
608 return FQName(message.package(),
609 GetVersionString(message.component_type_version()),
610 GetComponentName(message));
611 }
612
613 } // namespace vts
614 } // namespace android
615