Home | History | Annotate | Download | only in driver
      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 "code_gen/driver/HalCodeGen.h"
     18 
     19 #include <iostream>
     20 #include <string>
     21 
     22 #include "VtsCompilerUtils.h"
     23 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
     24 #include "utils/InterfaceSpecUtil.h"
     25 #include "utils/StringUtil.h"
     26 
     27 using namespace std;
     28 using namespace android;
     29 
     30 namespace android {
     31 namespace vts {
     32 
     33 const char* const HalCodeGen::kInstanceVariableName = "device_";
     34 
     35 void HalCodeGen::GenerateCppBodyInterfaceImpl(
     36     Formatter& out, const ComponentSpecificationMessage& message,
     37     const string& fuzzer_extended_class_name) {
     38   bool first_callback = true;
     39 
     40   for (int i = 0; i < message.interface().attribute_size(); i++) {
     41     const VariableSpecificationMessage& attribute = message.interface().attribute(i);
     42     if (attribute.type() != TYPE_FUNCTION_POINTER || !attribute.is_callback()) {
     43       continue;
     44     }
     45     string name =
     46         "vts_callback_" + fuzzer_extended_class_name + "_" + attribute.name();
     47     if (first_callback) {
     48       out << "static string callback_socket_name_;" << "\n";
     49       first_callback = false;
     50     }
     51     out << "\n";
     52     out << "class " << name << " : public DriverCallbackBase {"
     53         << "\n";
     54     out << " public:" << "\n";
     55     out.indent();
     56     out << name << "(const string& callback_socket_name) {" << "\n";
     57     out.indent();
     58     out << "callback_socket_name_ = callback_socket_name;" << "\n";
     59     out.unindent();
     60     out << "}" << "\n";
     61 
     62     int primitive_format_index = 0;
     63     for (const FunctionPointerSpecificationMessage& func_pt_spec :
     64          attribute.function_pointer()) {
     65       const string& callback_name = func_pt_spec.function_name();
     66       // TODO: callback's return value is assumed to be 'void'.
     67       out << "\n";
     68       out << "static ";
     69       bool has_return_value = false;
     70       if (!func_pt_spec.has_return_type() ||
     71           !func_pt_spec.return_type().has_type() ||
     72           func_pt_spec.return_type().type() == TYPE_VOID) {
     73         out << "void" << "\n";
     74       } else if (func_pt_spec.return_type().type() == TYPE_PREDEFINED) {
     75         out << func_pt_spec.return_type().predefined_type();
     76         has_return_value = true;
     77       } else {
     78         cerr << __func__ << ":" << __LINE__ << " ERROR unknown type "
     79              << func_pt_spec.return_type().type() << "\n";
     80         exit(-1);
     81       }
     82       out << " " << callback_name << "(";
     83       int primitive_type_index;
     84       primitive_type_index = 0;
     85       for (const auto& arg : func_pt_spec.arg()) {
     86         if (primitive_type_index != 0) {
     87           out << ", ";
     88         }
     89         if (arg.is_const()) {
     90           out << "const ";
     91         }
     92         if (arg.type() == TYPE_SCALAR) {
     93           /*
     94           if (arg.scalar_type() == "pointer") {
     95             out << definition.aggregate_value(
     96                 primitive_format_index).primitive_name(primitive_type_index)
     97                     << " ";
     98           } */
     99           if (arg.scalar_type() == "char_pointer") {
    100             out << "char* ";
    101           } else if (arg.scalar_type() == "uchar_pointer") {
    102             out << "unsigned char* ";
    103           } else if (arg.scalar_type() == "bool_t") {
    104             out << "bool ";
    105           } else if (arg.scalar_type() == "int8_t" ||
    106                      arg.scalar_type() == "uint8_t" ||
    107                      arg.scalar_type() == "int16_t" ||
    108                      arg.scalar_type() == "uint16_t" ||
    109                      arg.scalar_type() == "int32_t" ||
    110                      arg.scalar_type() == "uint32_t" ||
    111                      arg.scalar_type() == "size_t" ||
    112                      arg.scalar_type() == "int64_t" ||
    113                      arg.scalar_type() == "uint64_t") {
    114             out << arg.scalar_type() << " ";
    115           } else if (arg.scalar_type() == "void_pointer") {
    116             out << "void*";
    117           } else {
    118             cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
    119                  << "\n";
    120             exit(-1);
    121           }
    122         } else if (arg.type() == TYPE_PREDEFINED) {
    123           out << arg.predefined_type() << " ";
    124         } else {
    125           cerr << __func__ << " unsupported type" << "\n";
    126           exit(-1);
    127         }
    128         out << "arg" << primitive_type_index;
    129         primitive_type_index++;
    130       }
    131       out << ") {" << "\n";
    132       out.indent();
    133 #if USE_VAARGS
    134       out << "    const char fmt[] = \""
    135              << definition.primitive_format(primitive_format_index) << "\";"
    136              << "\n";
    137       out << "    va_list argp;" << "\n";
    138       out << "    const char* p;" << "\n";
    139       out << "    int i;" << "\n";
    140       out << "    char* s;" << "\n";
    141       out << "    char fmtbuf[256];" << "\n";
    142       out << "\n";
    143       out << "    va_start(argp, fmt);" << "\n";
    144       out << "\n";
    145       out << "    for (p = fmt; *p != '\\0'; p++) {" << "\n";
    146       out << "      if (*p != '%') {" << "\n";
    147       out << "        putchar(*p);" << "\n";
    148       out << "        continue;" << "\n";
    149       out << "      }" << "\n";
    150       out << "      switch (*++p) {" << "\n";
    151       out << "        case 'c':" << "\n";
    152       out << "          i = va_arg(argp, int);" << "\n";
    153       out << "          putchar(i);" << "\n";
    154       out << "          break;" << "\n";
    155       out << "        case 'd':" << "\n";
    156       out << "          i = va_arg(argp, int);" << "\n";
    157       out << "          s = itoa(i, fmtbuf, 10);" << "\n";
    158       out << "          fputs(s, stdout);" << "\n";
    159       out << "          break;" << "\n";
    160       out << "        case 's':" << "\n";
    161       out << "          s = va_arg(argp, char *);" << "\n";
    162       out << "          fputs(s, stdout);" << "\n";
    163       out << "          break;" << "\n";
    164       // out << "        case 'p':
    165       out << "        case '%':" << "\n";
    166       out << "          putchar('%');" << "\n";
    167       out << "          break;" << "\n";
    168       out << "      }" << "\n";
    169       out << "    }" << "\n";
    170       out << "    va_end(argp);" << "\n";
    171 #endif
    172       // TODO: check whether bytes is set and handle properly if not.
    173       out << "AndroidSystemCallbackRequestMessage callback_message;"
    174              << "\n";
    175       out << "callback_message.set_id(GetCallbackID(\"" << callback_name
    176              << "\"));" << "\n";
    177 
    178       primitive_type_index = 0;
    179       for (const auto& arg : func_pt_spec.arg()) {
    180         out << "VariableSpecificationMessage* var_msg" << primitive_type_index
    181                << " = callback_message.add_arg();" << "\n";
    182         if (arg.type() == TYPE_SCALAR) {
    183           out << "var_msg" << primitive_type_index << "->set_type("
    184                  << "TYPE_SCALAR);" << "\n";
    185           out << "var_msg" << primitive_type_index << "->set_scalar_type(\""
    186                  << arg.scalar_type() << "\");" << "\n";
    187           out << "var_msg" << primitive_type_index << "->mutable_scalar_value()";
    188           if (arg.scalar_type() == "bool_t") {
    189             out << "->set_" << arg.scalar_type() << "("
    190                 << arg.scalar_value().bool_t() << ");" << "\n";
    191           } else if (arg.scalar_type() == "int8_t") {
    192             out << "->set_" << arg.scalar_type() << "("
    193                 << arg.scalar_value().int8_t() << ");" << "\n";
    194           } else if (arg.scalar_type() == "uint8_t") {
    195             out << "->set_" << arg.scalar_type() << "("
    196                 << arg.scalar_value().uint8_t() << ");" << "\n";
    197           } else if (arg.scalar_type() == "int16_t") {
    198             out << "->set_" << arg.scalar_type() << "("
    199                 << arg.scalar_value().int16_t() << ");" << "\n";
    200           } else if (arg.scalar_type() == "uint16_t") {
    201             out << "->set_" << arg.scalar_type() << "("
    202                 << arg.scalar_value().uint16_t() << ");" << "\n";
    203           } else if (arg.scalar_type() == "int32_t") {
    204             out << "->set_" << arg.scalar_type() << "("
    205                 << arg.scalar_value().int32_t() << ");" << "\n";
    206           } else if (arg.scalar_type() == "uint32_t") {
    207             out << "->set_" << arg.scalar_type() << "("
    208                 << arg.scalar_value().uint32_t() << ");" << "\n";
    209           } else if (arg.scalar_type() == "size_t") {
    210             out << "->set_uint32_t("
    211                 << arg.scalar_value().uint32_t() << ");" << "\n";
    212           } else if (arg.scalar_type() == "int64_t") {
    213             out << "->set_" << arg.scalar_type() << "("
    214                 << arg.scalar_value().int64_t() << ");" << "\n";
    215           } else if (arg.scalar_type() == "uint64_t") {
    216             out << "->set_" << arg.scalar_type() << "("
    217                 << arg.scalar_value().uint64_t() << ");" << "\n";
    218           } else if (arg.scalar_type() == "char_pointer") {
    219             // pointer value is not meaning when it is passed to another machine.
    220             out << "->set_" << arg.scalar_type() << "("
    221                 << arg.scalar_value().char_pointer() << ");" << "\n";
    222           } else if (arg.scalar_type() == "uchar_pointer") {
    223             // pointer value is not meaning when it is passed to another machine.
    224             out << "->set_" << arg.scalar_type() << "("
    225                 << arg.scalar_value().uchar_pointer() << ");" << "\n";
    226           } else if (arg.scalar_type() == "void_pointer") {
    227             // pointer value is not meaning when it is passed to another machine.
    228             out << "->set_" << arg.scalar_type() << "("
    229                 << arg.scalar_value().void_pointer() << ");" << "\n";
    230           } else {
    231             cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
    232                  << "\n";
    233             exit(-1);
    234           }
    235         } else if (arg.type() == TYPE_PREDEFINED) {
    236           out << "var_msg" << primitive_type_index << "->set_type("
    237               << "TYPE_PREDEFINED);" << "\n";
    238           // TODO: actually handle such case.
    239         } else {
    240           cerr << __func__ << " unsupported type" << "\n";
    241           exit(-1);
    242         }
    243         primitive_type_index++;
    244       }
    245       out << "RpcCallToAgent(callback_message, callback_socket_name_);"
    246           << "\n";
    247       if (has_return_value) {
    248         // TODO: consider actual return type.
    249         out << "return NULL;";
    250       }
    251       out.unindent();
    252       out << "}" << "\n";
    253       out << "\n";
    254 
    255       primitive_format_index++;
    256     }
    257     out << "\n";
    258     out.unindent();
    259     out << " private:" << "\n";
    260     out << "};" << "\n";
    261     out << "\n";
    262   }
    263 }
    264 
    265 void HalCodeGen::GenerateCppBodyFuzzFunction(
    266     Formatter& out, const ComponentSpecificationMessage& message,
    267     const string& fuzzer_extended_class_name) {
    268   for (auto const& sub_struct : message.interface().sub_struct()) {
    269     GenerateCppBodyFuzzFunction(out, sub_struct, fuzzer_extended_class_name,
    270                                 message.original_data_structure_name(),
    271                                 sub_struct.is_pointer() ? "->" : ".");
    272   }
    273 
    274   out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
    275   out << "    FunctionSpecificationMessage* func_msg," << "\n";
    276   out << "    void** result, const string& callback_socket_name) {" << "\n";
    277   out.indent();
    278   out << "const char* func_name = func_msg->name().c_str();" << "\n";
    279   out << "LOG(INFO) << \" '\" << func_name << \"'\";"
    280       << "\n";
    281 
    282   // to call another function if it's for a sub_struct
    283   if (message.interface().sub_struct().size() > 0) {
    284     out << "if (func_msg->parent_path().length() > 0) {" << "\n";
    285     out.indent();
    286     for (auto const& sub_struct : message.interface().sub_struct()) {
    287       GenerateSubStructFuzzFunctionCall(out, sub_struct, "");
    288     }
    289     out.unindent();
    290     out << "}" << "\n";
    291   }
    292 
    293   out << message.original_data_structure_name()
    294       << "* local_device = ";
    295   out << "reinterpret_cast<" << message.original_data_structure_name()
    296       << "*>(" << kInstanceVariableName << ");" << "\n";
    297 
    298   out << "if (local_device == NULL) {" << "\n";
    299   out.indent();
    300   out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;"
    301       << "\n";
    302   out << "local_device = reinterpret_cast<"
    303       << message.original_data_structure_name() << "*>(hmi_);\n";
    304   out.unindent();
    305   out << "}" << "\n";
    306   out << "if (local_device == NULL) {" << "\n";
    307   out.indent();
    308   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
    309   out << "return false;" << "\n";
    310   out.unindent();
    311   out << "}" << "\n";
    312 
    313   for (auto const& api : message.interface().api()) {
    314     out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
    315     out.indent();
    316     out << "LOG(INFO) << \"match\" <<;\n";
    317     // args - definition;
    318     int arg_count = 0;
    319     for (auto const& arg : api.arg()) {
    320       if (arg.is_callback()) {  // arg.type() isn't always TYPE_FUNCTION_POINTER
    321         string name = "vts_callback_" + fuzzer_extended_class_name + "_" +
    322                       arg.predefined_type();  // TODO - check to make sure name
    323                                               // is always correct
    324         if (name.back() == '*') name.pop_back();
    325         out << name << "* arg" << arg_count << "callback = new ";
    326         out << name << "(callback_socket_name);" << "\n";
    327         out << "arg" << arg_count << "callback->Register(func_msg->arg("
    328             << arg_count << "));" << "\n";
    329 
    330         out << GetCppVariableType(arg) << " ";
    331         out << "arg" << arg_count << " = (" << GetCppVariableType(arg)
    332             << ") malloc(sizeof(" << GetCppVariableType(arg) << "));"
    333             << "\n";
    334         // TODO: think about how to free the malloced callback data structure.
    335         // find the spec.
    336         bool found = false;
    337         cout << name << "\n";
    338         for (auto const& attribute : message.interface().attribute()) {
    339           if (attribute.type() == TYPE_FUNCTION_POINTER &&
    340               attribute.is_callback()) {
    341             string target_name = "vts_callback_" + fuzzer_extended_class_name +
    342                                  "_" + attribute.name();
    343             cout << "compare" << "\n";
    344             cout << target_name << "\n";
    345             if (name == target_name) {
    346               if (attribute.function_pointer_size() > 1) {
    347                 for (auto const& func_pt : attribute.function_pointer()) {
    348                   out << "arg" << arg_count << "->"
    349                       << func_pt.function_name() << " = arg" << arg_count
    350                       << "callback->" << func_pt.function_name() << ";"
    351                       << "\n";
    352                 }
    353               } else {
    354                 out << "arg" << arg_count << " = arg" << arg_count
    355                     << "callback->" << attribute.name() << ";" << "\n";
    356               }
    357               found = true;
    358               break;
    359             }
    360           }
    361         }
    362         if (!found) {
    363           cerr << __func__ << " ERROR callback definition missing for " << name
    364                << " of " << api.name() << "\n";
    365           exit(-1);
    366         }
    367       } else {
    368         out << GetCppVariableType(arg) << " ";
    369         out << "arg" << arg_count << " = ";
    370         if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
    371             !strncmp(arg.predefined_type().c_str(),
    372                      message.original_data_structure_name().c_str(),
    373                      message.original_data_structure_name().length())) {
    374           out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
    375                  << kInstanceVariableName << ")";
    376         } else {
    377           std::stringstream msg_ss;
    378           msg_ss << "func_msg->arg(" << arg_count << ")";
    379           string msg = msg_ss.str();
    380 
    381           if (arg.type() == TYPE_SCALAR) {
    382             out << "(" << msg << ".type() == TYPE_SCALAR)? ";
    383             if (arg.scalar_type() == "pointer" ||
    384                 arg.scalar_type() == "pointer_pointer" ||
    385                 arg.scalar_type() == "char_pointer" ||
    386                 arg.scalar_type() == "uchar_pointer" ||
    387                 arg.scalar_type() == "void_pointer" ||
    388                 arg.scalar_type() == "function_pointer") {
    389               out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
    390             }
    391             out << "(" << msg << ".scalar_value()";
    392 
    393             if (arg.scalar_type() == "bool_t" ||
    394                 arg.scalar_type() == "int32_t" ||
    395                 arg.scalar_type() == "uint32_t" ||
    396                 arg.scalar_type() == "int64_t" ||
    397                 arg.scalar_type() == "uint64_t" ||
    398                 arg.scalar_type() == "int16_t" ||
    399                 arg.scalar_type() == "uint16_t" ||
    400                 arg.scalar_type() == "int8_t" ||
    401                 arg.scalar_type() == "uint8_t" ||
    402                 arg.scalar_type() == "float_t" ||
    403                 arg.scalar_type() == "double_t") {
    404               out << "." << arg.scalar_type() << "() ";
    405             } else if (arg.scalar_type() == "pointer" ||
    406                        arg.scalar_type() == "char_pointer" ||
    407                        arg.scalar_type() == "uchar_pointer" ||
    408                        arg.scalar_type() == "void_pointer") {
    409               out << ".pointer() ";
    410             } else {
    411               cerr << __func__ << " ERROR unsupported scalar type "
    412                    << arg.scalar_type() << "\n";
    413               exit(-1);
    414             }
    415             out << ") : ";
    416           } else {
    417             cerr << __func__ << " unknown type " << msg << "\n";
    418           }
    419 
    420           out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
    421                  << ".type() == TYPE_STRUCT || " << msg
    422                  << ".type() == TYPE_SCALAR)? ";
    423           out << GetCppInstanceType(arg, msg);
    424           out << " : " << GetCppInstanceType(arg) << " )";
    425           // TODO: use the given message and call a lib function which converts
    426           // a message to a C/C++ struct.
    427         }
    428         out << ";" << "\n";
    429       }
    430       out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
    431           << ";\n";
    432       arg_count++;
    433     }
    434 
    435     // actual function call
    436     GenerateCodeToStartMeasurement(out);
    437     out << "LOG(INFO) << \"hit2.\" << device_;\n";
    438 
    439     // checks whether the function is actually defined.
    440     out << "if (reinterpret_cast<"
    441            << message.original_data_structure_name() << "*>(local_device)->"
    442            << api.name() << " == NULL" << ") {" << "\n";
    443     out.indent();
    444     out << "LOG(ERROR) << \"api not set.\";\n";
    445     // todo: consider throwing an exception at least a way to tell more
    446     // specifically to the caller.
    447     out << "return false;" << "\n";
    448     out.unindent();
    449     out << "}" << "\n";
    450 
    451     out << "LOG(INFO) << \"Call an API.\";\n";
    452     out << "LOG(INFO) << \"local_device = \" << local_device;\n";
    453 
    454     if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
    455       out << "*result = NULL;" << "\n";
    456     } else {
    457       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
    458     }
    459     out << "local_device->" << api.name() << "(";
    460     if (arg_count > 0) out << "\n";
    461 
    462     for (int index = 0; index < arg_count; index++) {
    463       out << "arg" << index;
    464       if (index != (arg_count - 1)) {
    465         out << "," << "\n";
    466       }
    467     }
    468 
    469     if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
    470       out << "))";
    471     }
    472     out << ");" << "\n";
    473     GenerateCodeToStopMeasurement(out);
    474     out << "LOG(INFO) << \"called\";\n";
    475 
    476     // Copy the output (call by pointer or reference cases).
    477     arg_count = 0;
    478     for (auto const& arg : api.arg()) {
    479       if (arg.is_output()) {
    480         // TODO check the return value
    481         out << GetConversionToProtobufFunctionName(arg) << "(arg"
    482             << arg_count << ", "
    483             << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
    484       }
    485       arg_count++;
    486     }
    487 
    488     out << "return true;" << "\n";
    489     out.unindent();
    490     out << "}" << "\n";
    491   }
    492   // TODO: if there were pointers, free them.
    493   out << "LOG(ERROR) << \"func not found\";\n";
    494   out << "return false;" << "\n";
    495   out.unindent();
    496   out << "}" << "\n";
    497 }
    498 
    499 void HalCodeGen::GenerateCppBodyFuzzFunction(
    500     Formatter& out, const StructSpecificationMessage& message,
    501     const string& fuzzer_extended_class_name,
    502     const string& original_data_structure_name, const string& parent_path) {
    503   for (auto const& sub_struct : message.sub_struct()) {
    504     GenerateCppBodyFuzzFunction(
    505         out, sub_struct, fuzzer_extended_class_name,
    506         original_data_structure_name,
    507         parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
    508   }
    509 
    510   string parent_path_printable(parent_path);
    511   ReplaceSubString(parent_path_printable, "->", "_");
    512   replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
    513 
    514   out << "bool " << fuzzer_extended_class_name << "::Fuzz_"
    515          << parent_path_printable + message.name() << "(" << "\n";
    516   out << "FunctionSpecificationMessage* func_msg," << "\n";
    517   out << "void** result, const string& callback_socket_name) {" << "\n";
    518   out.indent();
    519   out << "const char* func_name = func_msg->name().c_str();" << "\n";
    520   out << "LOG(INFO) << func_name;\n";
    521 
    522   bool is_open;
    523   for (auto const& api : message.api()) {
    524     is_open = false;
    525     if ((parent_path_printable + message.name()) == "_common_methods" &&
    526         api.name() == "open") {
    527       is_open = true;
    528     }
    529 
    530     out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
    531     out.indent();
    532 
    533     out << original_data_structure_name << "* local_device = ";
    534     out << "reinterpret_cast<" << original_data_structure_name << "*>("
    535            << kInstanceVariableName << ");" << "\n";
    536 
    537     out << "if (local_device == NULL) {" << "\n";
    538     out.indent();
    539     out << "LOG(INFO) << \"use hmi\";\n";
    540     out << "local_device = reinterpret_cast<"
    541            << original_data_structure_name << "*>(hmi_);" << "\n";
    542     out.unindent();
    543     out << "}" << "\n";
    544     out << "if (local_device == NULL) {" << "\n";
    545     out.indent();
    546     out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
    547     out << "return false;" << "\n";
    548     out.unindent();
    549     out << "}" << "\n";
    550 
    551     // args - definition;
    552     int arg_count = 0;
    553     for (auto const& arg : api.arg()) {
    554       out << GetCppVariableType(arg) << " ";
    555       out << "arg" << arg_count << " = ";
    556       if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
    557           !strncmp(arg.predefined_type().c_str(),
    558                    original_data_structure_name.c_str(),
    559                    original_data_structure_name.length())) {
    560         out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
    561                << kInstanceVariableName << ")";
    562       } else {
    563         std::stringstream msg_ss;
    564         msg_ss << "func_msg->arg(" << arg_count << ")";
    565         string msg = msg_ss.str();
    566 
    567         if (arg.type() == TYPE_SCALAR) {
    568           out << "(" << msg << ".type() == TYPE_SCALAR && " << msg
    569                  << ".scalar_value()";
    570           if (arg.scalar_type() == "pointer" ||
    571               arg.scalar_type() == "char_pointer" ||
    572               arg.scalar_type() == "uchar_pointer" ||
    573               arg.scalar_type() == "void_pointer" ||
    574               arg.scalar_type() == "function_pointer") {
    575             out << ".has_pointer())? ";
    576             out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
    577           } else {
    578             out << ".has_" << arg.scalar_type() << "())? ";
    579           }
    580           out << "(" << msg << ".scalar_value()";
    581 
    582           if (arg.scalar_type() == "int32_t" ||
    583               arg.scalar_type() == "uint32_t" ||
    584               arg.scalar_type() == "int64_t" ||
    585               arg.scalar_type() == "uint64_t" ||
    586               arg.scalar_type() == "int16_t" ||
    587               arg.scalar_type() == "uint16_t" ||
    588               arg.scalar_type() == "int8_t" || arg.scalar_type() == "uint8_t" ||
    589               arg.scalar_type() == "float_t" ||
    590               arg.scalar_type() == "double_t") {
    591             out << "." << arg.scalar_type() << "() ";
    592           } else if (arg.scalar_type() == "pointer" ||
    593                      arg.scalar_type() == "char_pointer" ||
    594                      arg.scalar_type() == "uchar_pointer" ||
    595                      arg.scalar_type() == "function_pointer" ||
    596                      arg.scalar_type() == "void_pointer") {
    597             out << ".pointer() ";
    598           } else {
    599             cerr << __func__ << " ERROR unsupported type " << arg.scalar_type()
    600                  << "\n";
    601             exit(-1);
    602           }
    603           out << ") : ";
    604         }
    605 
    606         if (is_open) {
    607           if (arg_count == 0) {
    608             out << "hmi_;" << "\n";
    609           } else if (arg_count == 1) {
    610             out << "((hmi_) ? const_cast<char*>(hmi_->name) : NULL)" << "\n";
    611           } else if (arg_count == 2) {
    612             out << "(struct hw_device_t**) &device_" << "\n";
    613           } else {
    614             cerr << __func__ << " ERROR additional args for open " << arg_count
    615                  << "\n";
    616             exit(-1);
    617           }
    618         } else {
    619           out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
    620                  << ".type() == TYPE_STRUCT || " << msg
    621                  << ".type() == TYPE_SCALAR)? ";
    622           out << GetCppInstanceType(arg, msg);
    623           out << " : " << GetCppInstanceType(arg) << " )";
    624           // TODO: use the given message and call a lib function which converts
    625           // a message to a C/C++ struct.
    626         }
    627       }
    628       out << ";" << "\n";
    629       out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
    630           << "\n\n";
    631       arg_count++;
    632     }
    633 
    634     // actual function call
    635     GenerateCodeToStartMeasurement(out);
    636     out << "LOG(INFO) << \"hit2.\" << device_;\n";
    637 
    638     out << "if (reinterpret_cast<" << original_data_structure_name
    639            << "*>(local_device)" << parent_path << message.name() << "->"
    640            << api.name() << " == NULL";
    641     out << ") {" << "\n";
    642     out.indent();
    643     out << "LOG(ERROR) << \"api not set.\";\n";
    644     // todo: consider throwing an exception at least a way to tell more
    645     // specifically to the caller.
    646     out << "return false;" << "\n";
    647     out.unindent();
    648     out << "}" << "\n";
    649 
    650     out << "LOG(INFO) << \"Call an API.\";\n";
    651     if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
    652       out << "*result = NULL;" << "\n";
    653     } else {
    654       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
    655     }
    656     out << "local_device" << parent_path << message.name() << "->"
    657         << api.name() << "(";
    658     if (arg_count > 0) out << "\n";
    659 
    660     for (int index = 0; index < arg_count; index++) {
    661       out << "arg" << index;
    662       if (index != (arg_count - 1)) {
    663         out << "," << "\n";
    664       }
    665     }
    666     if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
    667       out << "))";
    668     }
    669     out << ");" << "\n";
    670     GenerateCodeToStopMeasurement(out);
    671     out << "LOG(INFO) << \"called\";\n";
    672 
    673     // Copy the output (call by pointer or reference cases).
    674     arg_count = 0;
    675     for (auto const& arg : api.arg()) {
    676       if (arg.is_output()) {
    677         // TODO check the return value
    678         out << GetConversionToProtobufFunctionName(arg) << "(arg"
    679             << arg_count << ", "
    680             << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
    681       }
    682       arg_count++;
    683     }
    684 
    685     out << "return true;" << "\n";
    686     out.unindent();
    687     out << "}" << "\n";
    688   }
    689   // TODO: if there were pointers, free them.
    690   out << "return false;" << "\n";
    691   out.unindent();
    692   out << "}" << "\n";
    693 }
    694 
    695 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
    696     Formatter& out, const ComponentSpecificationMessage& message,
    697     const string& fuzzer_extended_class_name) {
    698   for (auto const& sub_struct : message.interface().sub_struct()) {
    699     GenerateCppBodyGetAttributeFunction(
    700         out, sub_struct, fuzzer_extended_class_name,
    701         message.original_data_structure_name(),
    702         sub_struct.is_pointer() ? "->" : ".");
    703   }
    704 
    705   out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
    706   out << "    FunctionSpecificationMessage* func_msg," << "\n";
    707   out << "    void** result) {" << "\n";
    708   out.indent();
    709   out << "const char* func_name = func_msg->name().c_str();" << "\n";
    710   out << "LOG(INFO) << \" '\" << func_name << \"'\";\n";
    711 
    712   // to call another function if it's for a sub_struct
    713   if (message.interface().sub_struct().size() > 0) {
    714     out << "  if (func_msg->parent_path().length() > 0) {" << "\n";
    715     out.indent();
    716     for (auto const& sub_struct : message.interface().sub_struct()) {
    717       GenerateSubStructGetAttributeFunctionCall(out, sub_struct, "");
    718     }
    719     out.unindent();
    720     out << "}" << "\n";
    721   }
    722 
    723   out << message.original_data_structure_name()
    724       << "* local_device = ";
    725   out << "reinterpret_cast<" << message.original_data_structure_name()
    726       << "*>(" << kInstanceVariableName << ");" << "\n";
    727 
    728   out << "if (local_device == NULL) {" << "\n";
    729   out.indent();
    730   out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
    731   out << "local_device = reinterpret_cast<"
    732          << message.original_data_structure_name() << "*>(hmi_);" << "\n";
    733   out.unindent();
    734   out << "}" << "\n";
    735   out << "if (local_device == NULL) {" << "\n";
    736   out.indent();
    737   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
    738   out << "return false;" << "\n";
    739   out.unindent();
    740   out << "}" << "\n";
    741 
    742   for (auto const& attribute : message.interface().attribute()) {
    743     if (attribute.type() == TYPE_SUBMODULE ||
    744         attribute.type() == TYPE_SCALAR) {
    745       out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
    746       out.indent();
    747       out << "LOG(INFO) << \"match\";\n";
    748 
    749       // actual function call
    750       out << "LOG(INFO) << \"hit2.\" << device_ ;\n";
    751 
    752       out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
    753       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
    754       out << "local_device->" << attribute.name();
    755       out << "));" << "\n";
    756 
    757       out << "LOG(INFO) << \"got\";\n";
    758 
    759       out << "return true;" << "\n";
    760       out.unindent();
    761       out << "}" << "\n";
    762     }
    763   }
    764   // TODO: if there were pointers, free them.
    765   out << "LOG(ERROR) << \"attribute not found\";\n";
    766   out << "return false;" << "\n";
    767   out.unindent();
    768   out << "}" << "\n";
    769 }
    770 
    771 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
    772     Formatter& out, const StructSpecificationMessage& message,
    773     const string& fuzzer_extended_class_name,
    774     const string& original_data_structure_name, const string& parent_path) {
    775   for (auto const& sub_struct : message.sub_struct()) {
    776     GenerateCppBodyGetAttributeFunction(
    777         out, sub_struct, fuzzer_extended_class_name,
    778         original_data_structure_name,
    779         parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
    780   }
    781 
    782   string parent_path_printable(parent_path);
    783   ReplaceSubString(parent_path_printable, "->", "_");
    784   replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
    785 
    786   out << "bool " << fuzzer_extended_class_name << "::GetAttribute_"
    787          << parent_path_printable + message.name() << "(" << "\n";
    788   out << "    FunctionSpecificationMessage* func_msg," << "\n";
    789   out << "    void** result) {" << "\n";
    790   out.indent();
    791   out << "const char* func_name = func_msg->name().c_str();" << "\n";
    792   out << "LOG(INFO) << func_name;\n";
    793 
    794   out << original_data_structure_name
    795       << "* local_device = ";
    796   out << "reinterpret_cast<" << original_data_structure_name
    797       << "*>(" << kInstanceVariableName << ");" << "\n";
    798 
    799   out << "if (local_device == NULL) {" << "\n";
    800   out.indent();
    801   out << "  LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
    802   out << "  local_device = reinterpret_cast<"
    803       << original_data_structure_name << "*>(hmi_);" << "\n";
    804   out.unindent();
    805   out << "}" << "\n";
    806   out << "if (local_device == NULL) {" << "\n";
    807   out.indent();
    808   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
    809   out << "return false;" << "\n";
    810   out.unindent();
    811   out << "}" << "\n";
    812 
    813   for (auto const& attribute : message.attribute()) {
    814     if (attribute.type() == TYPE_SUBMODULE ||
    815         attribute.type() == TYPE_SCALAR) {
    816       out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
    817       out.indent();
    818       out << "LOG(INFO) << \"match\";\n";
    819 
    820       // actual function call
    821       out << "LOG(INFO) << \"hit2.\" << device_;\n";
    822 
    823       out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
    824       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
    825       out << "local_device" << parent_path << message.name() << ".";
    826       // TODO: use parent's is_pointer()
    827       out << attribute.name();
    828       out << "));" << "\n";
    829 
    830       out << "LOG(INFO) << \"got\";\n";
    831 
    832       out << "return true;" << "\n";
    833       out.unindent();
    834       out << "}" << "\n";
    835     }
    836   }
    837   // TODO: if there were pointers, free them.
    838   out << "LOG(ERROR) << \"attribute not found\";\n";
    839   out << "return false;" << "\n";
    840   out.unindent();
    841   out << "}" << "\n";
    842 }
    843 
    844 void HalCodeGen::GenerateClassConstructionFunction(Formatter& out,
    845       const ComponentSpecificationMessage& /*message*/,
    846       const string& fuzzer_extended_class_name) {
    847   out << fuzzer_extended_class_name << "() : DriverBase(HAL_CONVENTIONAL) {}\n";
    848 }
    849 
    850 void HalCodeGen::GenerateSubStructFuzzFunctionCall(
    851     Formatter& out, const StructSpecificationMessage& message,
    852     const string& parent_path) {
    853   string current_path(parent_path);
    854   if (current_path.length() > 0) {
    855     current_path += ".";
    856   }
    857   current_path += message.name();
    858 
    859   string current_path_printable(current_path);
    860   replace(current_path_printable.begin(), current_path_printable.end(), '.',
    861           '_');
    862 
    863   out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
    864       << "\n";
    865   out.indent();
    866   out << "return Fuzz__" << current_path_printable
    867       << "(func_msg, result, callback_socket_name);" << "\n";
    868   out.unindent();
    869   out << "}" << "\n";
    870 
    871   for (auto const& sub_struct : message.sub_struct()) {
    872     GenerateSubStructFuzzFunctionCall(out, sub_struct, current_path);
    873   }
    874 }
    875 
    876 void HalCodeGen::GenerateSubStructGetAttributeFunctionCall(
    877     Formatter& out, const StructSpecificationMessage& message,
    878     const string& parent_path) {
    879   string current_path(parent_path);
    880   if (current_path.length() > 0) {
    881     current_path += ".";
    882   }
    883   current_path += message.name();
    884 
    885   string current_path_printable(current_path);
    886   replace(current_path_printable.begin(), current_path_printable.end(), '.',
    887           '_');
    888 
    889   out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
    890       << "\n";
    891   out.indent();
    892   out << "      return GetAttribute__" << current_path_printable
    893       << "(func_msg, result);" << "\n";
    894   out.unindent();
    895   out << "}" << "\n";
    896 
    897   for (auto const& sub_struct : message.sub_struct()) {
    898     GenerateSubStructGetAttributeFunctionCall(out, sub_struct, current_path);
    899   }
    900 }
    901 
    902 }  // namespace vts
    903 }  // namespace android
    904