• 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 "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