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