• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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