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