Home | History | Annotate | Download | only in vtsc
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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.
    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.
    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 
    557 string GetPackageName(const ComponentSpecificationMessage& message) {
    558   if (!message.package().empty()) {
    559     return message.package();
    560   }
    561   return "";
    562 }
    563 
    564 string GetPackagePath(const ComponentSpecificationMessage& message) {
    565   string package_path = GetPackageName(message);
    566   ReplaceSubString(package_path, ".", "/");
    567   return package_path;
    568 }
    569 
    570 string GetPackageNamespaceToken(const ComponentSpecificationMessage& message) {
    571   string package_token = GetPackageName(message);
    572   ReplaceSubString(package_token, ".", "::");
    573   return package_token;
    574 }
    575 
    576 string GetVersion(const ComponentSpecificationMessage& message,
    577                   bool for_macro) {
    578   return GetVersionString(message.component_type_version(), for_macro);
    579 }
    580 
    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 
    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 
    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