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