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/HalHidlCodeGen.h"
     18 
     19 #include <fstream>
     20 #include <iostream>
     21 #include <set>
     22 #include <sstream>
     23 #include <string>
     24 
     25 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
     26 
     27 #include "VtsCompilerUtils.h"
     28 #include "utils/InterfaceSpecUtil.h"
     29 #include "utils/StringUtil.h"
     30 
     31 using namespace std;
     32 using namespace android;
     33 
     34 namespace android {
     35 namespace vts {
     36 
     37 const char* const HalHidlCodeGen::kInstanceVariableName = "hw_binder_proxy_";
     38 
     39 void HalHidlCodeGen::GenerateCppBodyInterfaceImpl(
     40     Formatter& out, const ComponentSpecificationMessage& message,
     41     const string& /*fuzzer_extended_class_name*/) {
     42   out << "\n";
     43   FQName component_fq_name = GetFQName(message);
     44   for (const auto& api : message.interface().api()) {
     45     // Generate return statement.
     46     if (CanElideCallback(api)) {
     47       out << "::android::hardware::Return<"
     48           << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
     49     } else {
     50       out << "::android::hardware::Return<void> ";
     51     }
     52     // Generate function call.
     53     string full_method_name =
     54         "Vts_" + component_fq_name.tokenName() + "::" + api.name();
     55     out << full_method_name << "(\n";
     56     out.indent();
     57     for (int index = 0; index < api.arg_size(); index++) {
     58       const auto& arg = api.arg(index);
     59       if (!isConstType(arg.type())) {
     60         out << GetCppVariableType(arg, &message);
     61       } else {
     62         out << GetCppVariableType(arg, &message, true);
     63       }
     64       out << " arg" << index << " __attribute__((__unused__))";
     65       if (index != (api.arg_size() - 1)) out << ",\n";
     66     }
     67     if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
     68       out << ") {\n";
     69     } else {  // handle the case of callbacks.
     70       out << (api.arg_size() != 0 ? ", " : "");
     71       out << "std::function<void(";
     72       for (int index = 0; index < api.return_type_hidl_size(); index++) {
     73         const auto& return_val = api.return_type_hidl(index);
     74         if (!isConstType(return_val.type())) {
     75           out << GetCppVariableType(return_val, &message);
     76         } else {
     77           out << GetCppVariableType(return_val, &message, true);
     78         }
     79         out << " arg" << index;
     80         if (index != (api.return_type_hidl_size() - 1)) {
     81           out << ",";
     82         }
     83       }
     84       out << ")>) {\n";
     85     }
     86     out << "cout << \"" << api.name() << " called\" << endl;\n";
     87     out << "AndroidSystemCallbackRequestMessage callback_message;\n";
     88     out << "callback_message.set_id(GetCallbackID(\"" << api.name()
     89         << "\"));\n";
     90     out << "callback_message.set_name(\"" << full_method_name << "\");\n";
     91     for (int index = 0; index < api.arg_size(); index++) {
     92       out << "VariableSpecificationMessage* var_msg" << index << " = "
     93           << "callback_message.add_arg();\n";
     94       GenerateSetResultCodeForTypedVariable(out, api.arg(index),
     95                                             "var_msg" + std::to_string(index),
     96                                             "arg" + std::to_string(index));
     97     }
     98     out << "RpcCallToAgent(callback_message, callback_socket_name_);\n";
     99 
    100     // TODO(zhuoyao): return the received results from host.
    101     if (CanElideCallback(api)) {
    102       const auto& return_val = api.return_type_hidl(0);
    103       const auto& type = return_val.type();
    104       if (type == TYPE_SCALAR) {
    105         out << "return static_cast<"
    106             << GetCppVariableType(return_val.scalar_type()) << ">(0);\n";
    107       } else if (type == TYPE_ENUM || type == TYPE_MASK) {
    108         if (return_val.has_predefined_type()) {
    109           std::string predefined_type_name = return_val.predefined_type();
    110           ReplaceSubString(predefined_type_name, "::", "__");
    111           if (type == TYPE_ENUM) {
    112             out << "return static_cast< " << GetCppVariableType(return_val)
    113                 << ">(Random" << predefined_type_name << "());\n";
    114           } else {
    115             out << "return Random" << predefined_type_name << "();\n";
    116           }
    117         } else {
    118           cerr << __func__ << " ENUM doesn't have predefined type" << endl;
    119           exit(-1);
    120         }
    121       } else {
    122         out << "return nullptr;\n";
    123       }
    124     } else {
    125       out << "return ::android::hardware::Void();\n";
    126     }
    127     out.unindent();
    128     out << "}"
    129         << "\n";
    130     out << "\n";
    131   }
    132 
    133   string component_name_token = "Vts_" + component_fq_name.tokenName();
    134   out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
    135       << component_name_token << "(const string& callback_socket_name) {\n";
    136   out.indent();
    137   out << "static sp<" << component_fq_name.cppName() << "> result;\n";
    138   out << "result = new " << component_name_token << "(callback_socket_name);\n";
    139   out << "return result;\n";
    140   out.unindent();
    141   out << "}\n\n";
    142 }
    143 
    144 void HalHidlCodeGen::GenerateScalarTypeInC(Formatter& out, const string& type) {
    145   if (type == "bool_t") {
    146     out << "bool";
    147   } else if (type == "int8_t" ||
    148              type == "uint8_t" ||
    149              type == "int16_t" ||
    150              type == "uint16_t" ||
    151              type == "int32_t" ||
    152              type == "uint32_t" ||
    153              type == "int64_t" ||
    154              type == "uint64_t" ||
    155              type == "size_t") {
    156     out << type;
    157   } else if (type == "float_t") {
    158     out << "float";
    159   } else if (type == "double_t") {
    160     out << "double";
    161   } else if (type == "char_pointer") {
    162     out << "char*";
    163   } else if (type == "void_pointer") {
    164     out << "void*";
    165   } else {
    166     cerr << __func__ << ":" << __LINE__
    167          << " unsupported scalar type " << type << "\n";
    168     exit(-1);
    169   }
    170 }
    171 
    172 void HalHidlCodeGen::GenerateCppBodyFuzzFunction(
    173     Formatter& out, const ComponentSpecificationMessage& /*message*/,
    174     const string& fuzzer_extended_class_name) {
    175     out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
    176     out.indent();
    177     out << "FunctionSpecificationMessage* /*func_msg*/,"
    178         << "\n";
    179     out << "void** /*result*/, const string& /*callback_socket_name*/) {\n";
    180     out << "return true;\n";
    181     out.unindent();
    182     out << "}\n";
    183 }
    184 
    185 void HalHidlCodeGen::GenerateDriverFunctionImpl(Formatter& out,
    186     const ComponentSpecificationMessage& message,
    187     const string& fuzzer_extended_class_name) {
    188   if (message.component_name() != "types") {
    189     out << "bool " << fuzzer_extended_class_name << "::CallFunction("
    190         << "\n";
    191     out.indent();
    192     out << "const FunctionSpecificationMessage& func_msg,"
    193         << "\n";
    194     out << "const string& callback_socket_name __attribute__((__unused__)),"
    195         << "\n";
    196     out << "FunctionSpecificationMessage* result_msg) {\n";
    197 
    198     out << "const char* func_name = func_msg.name().c_str();" << "\n";
    199     out << "cout << \"Function: \" << __func__ << \" \" << func_name << endl;"
    200         << "\n";
    201     out << "cout << \"Callback socket name: \" << callback_socket_name << endl;"
    202         << "\n";
    203 
    204     out << "if (hw_binder_proxy_ == nullptr) {\n";
    205     out.indent();
    206     out << "cerr << \"" << kInstanceVariableName << " is null. \"<< endl;\n";
    207     out << "return false;\n";
    208     out.unindent();
    209     out << "}\n";
    210     for (auto const& api : message.interface().api()) {
    211       GenerateDriverImplForMethod(out, message, api);
    212     }
    213 
    214     GenerateDriverImplForReservedMethods(out);
    215 
    216     out << "return false;\n";
    217     out.unindent();
    218     out << "}\n";
    219   }
    220 }
    221 
    222 void HalHidlCodeGen::GenerateDriverImplForReservedMethods(Formatter& out) {
    223   // Generate call for reserved method: notifySyspropsChanged.
    224   out << "if (!strcmp(func_name, \"notifySyspropsChanged\")) {\n";
    225   out.indent();
    226 
    227   out << "cout << \"Call notifySyspropsChanged\" << endl;" << "\n";
    228   out << kInstanceVariableName << "->notifySyspropsChanged();\n";
    229   out << "result_msg->set_name(\"notifySyspropsChanged\");\n";
    230   out << "cout << \"called\" << endl;\n";
    231   out << "return true;\n";
    232 
    233   out.unindent();
    234   out << "}\n";
    235   // TODO(zhuoyao): Add generation code for other reserved method,
    236   // e.g interfaceChain
    237 }
    238 
    239 void HalHidlCodeGen::GenerateDriverImplForMethod(Formatter& out,
    240     const ComponentSpecificationMessage& message,
    241     const FunctionSpecificationMessage& func_msg) {
    242   out << "if (!strcmp(func_name, \"" << func_msg.name() << "\")) {\n";
    243   out.indent();
    244   // Process the arguments.
    245   for (int i = 0; i < func_msg.arg_size(); i++) {
    246     const auto& arg = func_msg.arg(i);
    247     string cur_arg_name = "arg" + std::to_string(i);
    248     string var_type;
    249     if (arg.type() == TYPE_ARRAY || arg.type() == TYPE_VECTOR) {
    250       var_type = GetCppVariableType(arg, &message, true);
    251       var_type = var_type.substr(5, var_type.length() - 6);
    252     } else {
    253       var_type = GetCppVariableType(arg, &message);
    254     }
    255     if (arg.type() == TYPE_POINTER ||
    256         (arg.type() == TYPE_SCALAR &&
    257          (arg.scalar_type() == "pointer" ||
    258           arg.scalar_type() == "void_pointer" ||
    259           arg.scalar_type() == "function_pointer"))) {
    260       out << var_type << " " << cur_arg_name << " = nullptr;\n";
    261     } else if (arg.type() == TYPE_SCALAR) {
    262       out << var_type << " " << cur_arg_name << " = 0;\n";
    263     } else if (arg.type() != TYPE_FMQ_SYNC && arg.type() != TYPE_FMQ_UNSYNC) {
    264       out << var_type << " " << cur_arg_name << ";\n";
    265     }
    266 
    267     GenerateDriverImplForTypedVariable(
    268         out, arg, cur_arg_name, "func_msg.arg(" + std::to_string(i) + ")");
    269   }
    270 
    271   GenerateCodeToStartMeasurement(out);
    272   // may need to check whether the function is actually defined.
    273   out << "cout << \"Call an API\" << endl;" << "\n";
    274   out << "cout << \"local_device = \" << " << kInstanceVariableName << ".get()"
    275       << " << endl;\n";
    276 
    277   // Define the return results and call the HAL function.
    278   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    279     const auto& return_val = func_msg.return_type_hidl(index);
    280     if (return_val.type() != TYPE_FMQ_SYNC &&
    281         return_val.type() != TYPE_FMQ_UNSYNC) {
    282       out << GetCppVariableType(return_val, &message) << " result" << index
    283           << ";\n";
    284     } else {
    285       // Use pointer to store return results with fmq type as copy assignment
    286       // is not allowed for fmq descriptor.
    287       out << "std::unique_ptr<" << GetCppVariableType(return_val, &message)
    288           << "> result" << index << ";\n";
    289     }
    290   }
    291   if (CanElideCallback(func_msg)) {
    292     out << "result0 = ";
    293     GenerateHalFunctionCall(out, message, func_msg);
    294   } else {
    295     GenerateHalFunctionCall(out, message, func_msg);
    296   }
    297 
    298   GenerateCodeToStopMeasurement(out);
    299 
    300   // Set the return results value to the proto message.
    301   out << "result_msg->set_name(\"" << func_msg.name() << "\");\n";
    302   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    303     out << "VariableSpecificationMessage* result_val_" << index << " = "
    304         << "result_msg->add_return_type_hidl();\n";
    305     GenerateSetResultCodeForTypedVariable(out, func_msg.return_type_hidl(index),
    306                                           "result_val_" + std::to_string(index),
    307                                           "result" + std::to_string(index));
    308   }
    309 
    310   out << "cout << \"called\" << endl;\n";
    311   out << "return true;\n";
    312   out.unindent();
    313   out << "}\n";
    314 }
    315 
    316 void HalHidlCodeGen::GenerateHalFunctionCall(Formatter& out,
    317     const ComponentSpecificationMessage& message,
    318     const FunctionSpecificationMessage& func_msg) {
    319   out << kInstanceVariableName << "->" << func_msg.name() << "(";
    320   for (int index = 0; index < func_msg.arg_size(); index++) {
    321     out << "arg" << index;
    322     if (index != (func_msg.arg_size() - 1)) out << ", ";
    323   }
    324   if (func_msg.return_type_hidl_size()== 0 || CanElideCallback(func_msg)) {
    325     out << ");\n";
    326   } else {
    327     out << (func_msg.arg_size() != 0 ? ", " : "");
    328     GenerateSyncCallbackFunctionImpl(out, message, func_msg);
    329     out << ");\n";
    330   }
    331 }
    332 
    333 void HalHidlCodeGen::GenerateSyncCallbackFunctionImpl(Formatter& out,
    334     const ComponentSpecificationMessage& message,
    335     const FunctionSpecificationMessage& func_msg) {
    336   out << "[&](";
    337   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    338     const auto& return_val = func_msg.return_type_hidl(index);
    339     if (!isConstType(return_val.type())) {
    340       out << GetCppVariableType(return_val, &message);
    341     } else {
    342       out << GetCppVariableType(return_val, &message, true);
    343     }
    344     out << " arg" << index;
    345     if (index != (func_msg.return_type_hidl_size() - 1)) out << ",";
    346   }
    347   out << "){\n";
    348   out.indent();
    349   out << "cout << \"callback " << func_msg.name() << " called\""
    350       << " << endl;\n";
    351 
    352   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    353     const auto& return_val = func_msg.return_type_hidl(index);
    354     if (return_val.type() != TYPE_FMQ_SYNC &&
    355         return_val.type() != TYPE_FMQ_UNSYNC) {
    356       out << "result" << index << " = arg" << index << ";\n";
    357     } else {
    358       out << "result" << index << ".reset(new (std::nothrow) "
    359           << GetCppVariableType(return_val, &message) << "(arg" << index
    360           << "));\n";
    361     }
    362   }
    363   out.unindent();
    364   out << "}";
    365 }
    366 
    367 void HalHidlCodeGen::GenerateCppBodyGetAttributeFunction(
    368     Formatter& out, const ComponentSpecificationMessage& message,
    369     const string& fuzzer_extended_class_name) {
    370   if (message.component_name() != "types") {
    371     out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
    372     out.indent();
    373     out << "FunctionSpecificationMessage* /*func_msg*/,"
    374         << "\n";
    375     out << "void** /*result*/) {"
    376         << "\n";
    377     // TOOD: impl
    378     out << "cerr << \"attribute not found\" << endl;\n"
    379         << "return false;\n";
    380     out.unindent();
    381     out << "}" << "\n";
    382   }
    383 }
    384 
    385 void HalHidlCodeGen::GenerateClassConstructionFunction(Formatter& out,
    386     const ComponentSpecificationMessage& message,
    387     const string& fuzzer_extended_class_name) {
    388   out << fuzzer_extended_class_name << "() : DriverBase(";
    389   if (message.component_name() != "types") {
    390     out << "HAL_HIDL), " << kInstanceVariableName << "()";
    391   } else {
    392     out << "HAL_HIDL)";
    393   }
    394   out << " {}" << "\n";
    395   out << "\n";
    396 
    397   FQName fqname = GetFQName(message);
    398   out << "explicit " << fuzzer_extended_class_name << "(" << fqname.cppName()
    399       << "* hw_binder_proxy) : DriverBase("
    400       << "HAL_HIDL)";
    401   if (message.component_name() != "types") {
    402     out << ", " << kInstanceVariableName << "(hw_binder_proxy)";
    403   }
    404   out << " {}\n";
    405 }
    406 
    407 void HalHidlCodeGen::GenerateHeaderGlobalFunctionDeclarations(Formatter& out,
    408     const ComponentSpecificationMessage& message,
    409     const bool print_extern_block) {
    410   if (message.component_name() != "types") {
    411     if (print_extern_block) {
    412       out << "extern \"C\" {" << "\n";
    413     }
    414     DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations(
    415         out, message, false);
    416 
    417     string function_name_prefix = GetFunctionNamePrefix(message);
    418     FQName fqname = GetFQName(message);
    419     out << "extern "
    420         << "android::vts::DriverBase* " << function_name_prefix
    421         << "with_arg(uint64_t hw_binder_proxy);\n";
    422     if (print_extern_block) {
    423       out << "}" << "\n";
    424     }
    425   }
    426 }
    427 
    428 void HalHidlCodeGen::GenerateCppBodyGlobalFunctions(Formatter& out,
    429     const ComponentSpecificationMessage& message,
    430     const string& fuzzer_extended_class_name, const bool print_extern_block) {
    431   if (message.component_name() != "types") {
    432     if (print_extern_block) {
    433       out << "extern \"C\" {" << "\n";
    434     }
    435     DriverCodeGenBase::GenerateCppBodyGlobalFunctions(
    436         out, message, fuzzer_extended_class_name, false);
    437 
    438     string function_name_prefix = GetFunctionNamePrefix(message);
    439     FQName fqname = GetFQName(message);
    440     out << "android::vts::DriverBase* " << function_name_prefix << "with_arg("
    441         << "uint64_t hw_binder_proxy) {\n";
    442     out.indent();
    443     out << fqname.cppName() << "* arg = nullptr;\n";
    444     out << "if (hw_binder_proxy) {\n";
    445     out.indent();
    446     out << "arg = reinterpret_cast<" << fqname.cppName()
    447         << "*>(hw_binder_proxy);\n";
    448     out.unindent();
    449     out << "} else {\n";
    450     out.indent();
    451     out << "cout << \" Creating DriverBase with null proxy.\" << endl;\n";
    452     out.unindent();
    453     out << "}\n";
    454     out << "android::vts::DriverBase* result ="
    455         << "\n"
    456         << "    new android::vts::" << fuzzer_extended_class_name << "(\n"
    457         << "        arg);\n";
    458     out << "if (arg != nullptr) {\n";
    459     out.indent();
    460     out << "arg->decStrong(arg);" << "\n";
    461     out.unindent();
    462     out << "}\n";
    463     out << "return result;" << "\n";
    464     out.unindent();
    465     out << "}\n\n";
    466     if (print_extern_block) {
    467       out << "}" << "\n";
    468     }
    469   }
    470 }
    471 
    472 void HalHidlCodeGen::GenerateClassHeader(Formatter& out,
    473     const ComponentSpecificationMessage& message,
    474     const string& fuzzer_extended_class_name) {
    475   if (message.component_name() != "types") {
    476     for (const auto attribute : message.interface().attribute()) {
    477       GenerateAllFunctionDeclForAttribute(out, attribute);
    478     }
    479     DriverCodeGenBase::GenerateClassHeader(out, message,
    480                                            fuzzer_extended_class_name);
    481   } else {
    482     for (const auto attribute : message.attribute()) {
    483       GenerateAllFunctionDeclForAttribute(out, attribute);
    484     };
    485   }
    486 }
    487 
    488 void HalHidlCodeGen::GenerateHeaderInterfaceImpl(
    489     Formatter& out, const ComponentSpecificationMessage& message) {
    490   out << "\n";
    491   FQName component_fq_name = GetFQName(message);
    492   string component_name_token = "Vts_" + component_fq_name.tokenName();
    493   out << "class " << component_name_token << " : public "
    494       << component_fq_name.cppName() << ", public DriverCallbackBase {\n";
    495   out << " public:\n";
    496   out.indent();
    497   out << component_name_token << "(const string& callback_socket_name)\n"
    498       << "    : callback_socket_name_(callback_socket_name) {};\n\n";
    499   out << "virtual ~" << component_name_token << "()"
    500       << " = default;\n\n";
    501   for (const auto& api : message.interface().api()) {
    502     // Generate return statement.
    503     if (CanElideCallback(api)) {
    504       out << "::android::hardware::Return<"
    505           << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
    506     } else {
    507       out << "::android::hardware::Return<void> ";
    508     }
    509     // Generate function call.
    510     out << api.name() << "(\n";
    511     out.indent();
    512     for (int index = 0; index < api.arg_size(); index++) {
    513       const auto& arg = api.arg(index);
    514       if (!isConstType(arg.type())) {
    515         out << GetCppVariableType(arg, &message);
    516       } else {
    517         out << GetCppVariableType(arg, &message, true);
    518       }
    519       out << " arg" << index;
    520       if (index != (api.arg_size() - 1)) out << ",\n";
    521     }
    522     if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
    523       out << ") override;\n\n";
    524     } else {  // handle the case of callbacks.
    525       out << (api.arg_size() != 0 ? ", " : "");
    526       out << "std::function<void(";
    527       for (int index = 0; index < api.return_type_hidl_size(); index++) {
    528         const auto& return_val = api.return_type_hidl(index);
    529         if (!isConstType(return_val.type())) {
    530           out << GetCppVariableType(return_val, &message);
    531         } else {
    532           out << GetCppVariableType(return_val, &message, true);
    533         }
    534         out << " arg" << index;
    535         if (index != (api.return_type_hidl_size() - 1)) out << ",";
    536       }
    537       out << ")>) override;\n\n";
    538     }
    539     out.unindent();
    540   }
    541   out << "\n";
    542   out.unindent();
    543   out << " private:\n";
    544   out.indent();
    545   out << "string callback_socket_name_;\n";
    546   out.unindent();
    547   out << "};\n\n";
    548 
    549   out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
    550       << component_name_token << "(const string& callback_socket_name);\n\n";
    551 }
    552 
    553 void HalHidlCodeGen::GenerateClassImpl(Formatter& out,
    554     const ComponentSpecificationMessage& message,
    555     const string& fuzzer_extended_class_name) {
    556   if (message.component_name() != "types") {
    557     for (auto attribute : message.interface().attribute()) {
    558       GenerateAllFunctionImplForAttribute(out, attribute);
    559     }
    560     GenerateGetServiceImpl(out, message, fuzzer_extended_class_name);
    561     DriverCodeGenBase::GenerateClassImpl(out, message,
    562                                          fuzzer_extended_class_name);
    563   } else {
    564     for (auto attribute : message.attribute()) {
    565       GenerateAllFunctionImplForAttribute(out, attribute);
    566     }
    567   }
    568 }
    569 
    570 void HalHidlCodeGen::GenerateHeaderIncludeFiles(Formatter& out,
    571     const ComponentSpecificationMessage& message,
    572     const string& fuzzer_extended_class_name) {
    573   DriverCodeGenBase::GenerateHeaderIncludeFiles(out, message,
    574                                                 fuzzer_extended_class_name);
    575   out << "#include <" << GetPackagePath(message) << "/" << GetVersion(message)
    576       << "/" << GetComponentName(message) << ".h>"
    577       << "\n";
    578   out << "#include <hidl/HidlSupport.h>" << "\n";
    579 
    580   for (const auto& import : message.import()) {
    581     FQName import_name = FQName(import);
    582     string import_package_path = import_name.package();
    583     string import_package_version = import_name.version();
    584     string import_component_name = import_name.name();
    585     ReplaceSubString(import_package_path, ".", "/");
    586 
    587     out << "#include <" << import_package_path << "/" << import_package_version
    588         << "/" << import_component_name << ".h>\n";
    589     if (import_package_path.find("android/hardware") != std::string::npos) {
    590       if (import_component_name[0] == 'I') {
    591         import_component_name = import_component_name.substr(1);
    592       }
    593       out << "#include <" << import_package_path << "/"
    594           << import_package_version << "/" << import_component_name
    595           << ".vts.h>\n";
    596     }
    597   }
    598   out << "\n\n";
    599 }
    600 
    601 void HalHidlCodeGen::GenerateSourceIncludeFiles(Formatter& out,
    602     const ComponentSpecificationMessage& message,
    603     const string& fuzzer_extended_class_name) {
    604   DriverCodeGenBase::GenerateSourceIncludeFiles(out, message,
    605                                                 fuzzer_extended_class_name);
    606   out << "#include <hidl/HidlSupport.h>\n";
    607   out << "#include <" << GetPackagePath(message) << "/" << GetVersion(message)
    608       << "/" << GetComponentName(message) << ".h>"
    609       << "\n";
    610   for (const auto& import : message.import()) {
    611     FQName import_name = FQName(import);
    612     string import_package_name = import_name.package();
    613     string import_package_version = import_name.version();
    614     string import_component_name = import_name.name();
    615     string import_package_path = import_package_name;
    616     ReplaceSubString(import_package_path, ".", "/");
    617     if (import_package_name == GetPackageName(message) &&
    618         import_package_version == GetVersion(message)) {
    619       out << "#include \"" << import_package_path << "/"
    620           << import_package_version << "/"
    621           << (import_component_name == "types"
    622                   ? "types"
    623                   : import_component_name.substr(1))
    624           << ".vts.h\"\n";
    625     } else {
    626       out << "#include <" << import_package_path << "/"
    627           << import_package_version << "/" << import_component_name << ".h>\n";
    628     }
    629   }
    630   out << "#include <android/hidl/allocator/1.0/IAllocator.h>\n";
    631   out << "#include <fmq/MessageQueue.h>\n";
    632   out << "#include <sys/stat.h>\n";
    633   out << "#include <unistd.h>\n";
    634 }
    635 
    636 void HalHidlCodeGen::GenerateAdditionalFuctionDeclarations(Formatter& out,
    637     const ComponentSpecificationMessage& message,
    638     const string& /*fuzzer_extended_class_name*/) {
    639   if (message.component_name() != "types") {
    640     out << "bool GetService(bool get_stub, const char* service_name);"
    641         << "\n\n";
    642   }
    643 }
    644 
    645 void HalHidlCodeGen::GeneratePublicFunctionDeclarations(
    646     Formatter& out, const ComponentSpecificationMessage& /*message*/) {
    647   out << "uint64_t GetHidlInterfaceProxy() const {\n";
    648   out.indent();
    649   out << "return reinterpret_cast<uintptr_t>(" << kInstanceVariableName
    650       << ".get());\n";
    651   out.unindent();
    652   out << "}\n";
    653 }
    654 
    655 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
    656     const ComponentSpecificationMessage& message) {
    657   FQName fqname = GetFQName(message);
    658   out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
    659 }
    660 
    661 void HalHidlCodeGen::GenerateRandomFunctionDeclForAttribute(Formatter& out,
    662     const VariableSpecificationMessage& attribute) {
    663   if (attribute.type() == TYPE_ENUM) {
    664     if (attribute.enum_value().enumerator_size() == 0) {
    665       // empty enum without any actual enumerator.
    666       return;
    667     }
    668     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
    669     out << attribute.enum_value().scalar_type() << " "
    670         << "Random" << attribute_name << "();\n";
    671   }
    672 }
    673 
    674 void HalHidlCodeGen::GenerateRandomFunctionImplForAttribute(Formatter& out,
    675     const VariableSpecificationMessage& attribute) {
    676   // Random value generator
    677   if (attribute.type() == TYPE_ENUM) {
    678     if (attribute.enum_value().enumerator_size() == 0) {
    679       // empty enum without any actual enumerator.
    680       return;
    681     }
    682     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
    683     out << attribute.enum_value().scalar_type() << " Random" << attribute_name
    684         << "() {\n";
    685     out.indent();
    686     out << attribute.enum_value().scalar_type() << " choice = " << "("
    687         << attribute.enum_value().scalar_type() << ") " << "rand() / "
    688         << attribute.enum_value().enumerator().size() << ";" << "\n";
    689     if (attribute.enum_value().scalar_type().find("u") != 0) {
    690       out << "if (choice < 0) choice *= -1;" << "\n";
    691     }
    692     for (int index = 0; index < attribute.enum_value().enumerator().size();
    693         index++) {
    694       out << "if (choice == ";
    695       out << "(" << attribute.enum_value().scalar_type() << ") ";
    696       if (attribute.enum_value().scalar_type() == "int8_t") {
    697         out << attribute.enum_value().scalar_value(index).int8_t();
    698       } else if (attribute.enum_value().scalar_type() == "uint8_t") {
    699         out << attribute.enum_value().scalar_value(index).uint8_t();
    700       } else if (attribute.enum_value().scalar_type() == "int16_t") {
    701         out << attribute.enum_value().scalar_value(index).int16_t();
    702       } else if (attribute.enum_value().scalar_type() == "uint16_t") {
    703         out << attribute.enum_value().scalar_value(index).uint16_t();
    704       } else if (attribute.enum_value().scalar_type() == "int32_t") {
    705         out << attribute.enum_value().scalar_value(index).int32_t();
    706       } else if (attribute.enum_value().scalar_type() == "uint32_t") {
    707         out << attribute.enum_value().scalar_value(index).uint32_t();
    708       } else if (attribute.enum_value().scalar_type() == "int64_t") {
    709         out << attribute.enum_value().scalar_value(index).int64_t();
    710       } else if (attribute.enum_value().scalar_type() == "uint64_t") {
    711         out << attribute.enum_value().scalar_value(index).uint64_t();
    712       } else {
    713         cerr << __func__ << ":" << __LINE__ << " ERROR unsupported enum type "
    714             << attribute.enum_value().scalar_type() << "\n";
    715         exit(-1);
    716       }
    717       out << ") return static_cast<" << attribute.enum_value().scalar_type()
    718           << ">(" << attribute.name()
    719           << "::" << attribute.enum_value().enumerator(index) << ");\n";
    720     }
    721     out << "return static_cast<" << attribute.enum_value().scalar_type() << ">("
    722         << attribute.name() << "::" << attribute.enum_value().enumerator(0)
    723         << ");\n";
    724     out.unindent();
    725     out << "}" << "\n";
    726   }
    727 }
    728 
    729 void HalHidlCodeGen::GenerateDriverDeclForAttribute(Formatter& out,
    730     const VariableSpecificationMessage& attribute) {
    731   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
    732     // Recursively generate SetResult method implementation for all sub_types.
    733     for (const auto sub_struct : attribute.sub_struct()) {
    734       GenerateDriverDeclForAttribute(out, sub_struct);
    735     }
    736     for (const auto sub_union : attribute.sub_union()) {
    737       GenerateDriverDeclForAttribute(out, sub_union);
    738     }
    739     string func_name = "MessageTo"
    740         + ClearStringWithNameSpaceAccess(attribute.name());
    741     out << "void " << func_name
    742         << "(const VariableSpecificationMessage& var_msg, " << attribute.name()
    743         << "* arg);\n";
    744   } else if (attribute.type() == TYPE_ENUM) {
    745     string func_name = "EnumValue"
    746             + ClearStringWithNameSpaceAccess(attribute.name());
    747     // Message to value converter
    748     out << attribute.name() << " " << func_name
    749         << "(const ScalarDataValueMessage& arg);\n";
    750   } else {
    751     cerr << __func__ << " unsupported attribute type " << attribute.type()
    752          << "\n";
    753     exit(-1);
    754   }
    755 }
    756 
    757 void HalHidlCodeGen::GenerateDriverImplForAttribute(Formatter& out,
    758     const VariableSpecificationMessage& attribute) {
    759   switch (attribute.type()) {
    760     case TYPE_ENUM:
    761     {
    762       string func_name = "EnumValue"
    763           + ClearStringWithNameSpaceAccess(attribute.name());
    764       // Message to value converter
    765       out << attribute.name() << " " << func_name
    766           << "(const ScalarDataValueMessage& arg) {\n";
    767       out.indent();
    768       out << "return (" << attribute.name() << ") arg."
    769           << attribute.enum_value().scalar_type() << "();\n";
    770       out.unindent();
    771       out << "}" << "\n";
    772       break;
    773     }
    774     case TYPE_STRUCT:
    775     {
    776       // Recursively generate driver implementation method for all sub_types.
    777       for (const auto sub_struct : attribute.sub_struct()) {
    778         GenerateDriverImplForAttribute(out, sub_struct);
    779       }
    780       string func_name = "MessageTo"
    781           + ClearStringWithNameSpaceAccess(attribute.name());
    782       out << "void " << func_name << "(const VariableSpecificationMessage& "
    783                                      "var_msg __attribute__((__unused__)), "
    784           << attribute.name() << "* arg __attribute__((__unused__))) {"
    785           << "\n";
    786       out.indent();
    787       int struct_index = 0;
    788       for (const auto& struct_value : attribute.struct_value()) {
    789         GenerateDriverImplForTypedVariable(
    790             out, struct_value, "arg->" + struct_value.name(),
    791             "var_msg.struct_value(" + std::to_string(struct_index) + ")");
    792         struct_index++;
    793       }
    794       out.unindent();
    795       out << "}\n";
    796       break;
    797     }
    798     case TYPE_UNION:
    799     {
    800       // Recursively generate driver implementation method for all sub_types.
    801       for (const auto sub_union : attribute.sub_union()) {
    802         GenerateDriverImplForAttribute(out, sub_union);
    803       }
    804       string func_name = "MessageTo"
    805           + ClearStringWithNameSpaceAccess(attribute.name());
    806       out << "void " << func_name
    807           << "(const VariableSpecificationMessage& var_msg, "
    808           << attribute.name() << "* arg) {" << "\n";
    809       out.indent();
    810       int union_index = 0;
    811       for (const auto& union_value : attribute.union_value()) {
    812         out << "if (var_msg.union_value(" << union_index << ").name() == \""
    813             << union_value.name() << "\") {" << "\n";
    814         out.indent();
    815         GenerateDriverImplForTypedVariable(
    816             out, union_value, "arg->" + union_value.name(),
    817             "var_msg.union_value(" + std::to_string(union_index) + ")");
    818         union_index++;
    819         out.unindent();
    820         out << "}" << "\n";
    821       }
    822       out.unindent();
    823       out << "}\n";
    824       break;
    825     }
    826     default:
    827     {
    828       cerr << __func__ << " unsupported attribute type " << attribute.type()
    829            << "\n";
    830       exit(-1);
    831     }
    832   }
    833 }
    834 
    835 void HalHidlCodeGen::GenerateGetServiceImpl(Formatter& out,
    836     const ComponentSpecificationMessage& message,
    837     const string& fuzzer_extended_class_name) {
    838   out << "bool " << fuzzer_extended_class_name
    839       << "::GetService(bool get_stub, const char* service_name) {" << "\n";
    840   out.indent();
    841   out << "static bool initialized = false;" << "\n";
    842   out << "if (!initialized) {" << "\n";
    843   out.indent();
    844   out << "cout << \"[agent:hal] HIDL getService\" << endl;" << "\n";
    845   out << "if (service_name) {\n"
    846       << "  cout << \"  - service name: \" << service_name << endl;" << "\n"
    847       << "}\n";
    848   FQName fqname = GetFQName(message);
    849   out << kInstanceVariableName << " = " << fqname.cppName() << "::getService("
    850       << "service_name, get_stub);" << "\n";
    851   out << "if (" << kInstanceVariableName << " == nullptr) {\n";
    852   out.indent();
    853   out << "cerr << \"getService() returned a null pointer.\" << endl;\n";
    854   out << "return false;\n";
    855   out.unindent();
    856   out << "}\n";
    857   out << "cout << \"[agent:hal] " << kInstanceVariableName << " = \" << "
    858       << kInstanceVariableName << ".get() << endl;" << "\n";
    859   out << "initialized = true;" << "\n";
    860   out.unindent();
    861   out << "}" << "\n";
    862   out << "return true;" << "\n";
    863   out.unindent();
    864   out << "}" << "\n" << "\n";
    865 }
    866 
    867 void HalHidlCodeGen::GenerateDriverImplForTypedVariable(Formatter& out,
    868     const VariableSpecificationMessage& val, const string& arg_name,
    869     const string& arg_value_name) {
    870   switch (val.type()) {
    871     case TYPE_SCALAR:
    872     {
    873       out << arg_name << " = " << arg_value_name << ".scalar_value()."
    874           << val.scalar_type() << "();\n";
    875       break;
    876     }
    877     case TYPE_STRING:
    878     {
    879       out << arg_name << " = ::android::hardware::hidl_string("
    880           << arg_value_name << ".string_value().message());\n";
    881       break;
    882     }
    883     case TYPE_ENUM:
    884     {
    885       if (val.has_predefined_type()) {
    886         string func_name = "EnumValue"
    887             + ClearStringWithNameSpaceAccess(val.predefined_type());
    888         out << arg_name << " = " << func_name << "(" << arg_value_name
    889             << ".scalar_value());\n";
    890       } else {
    891         out << arg_name << " = (" << val.name() << ")" << arg_value_name << "."
    892             << "enum_value().scalar_value(0)." << val.enum_value().scalar_type()
    893             << "();\n";
    894       }
    895       break;
    896     }
    897     case TYPE_MASK:
    898     {
    899       out << arg_name << " = " << arg_value_name << ".scalar_value()."
    900           << val.scalar_type() << "();\n";
    901       break;
    902     }
    903     case TYPE_VECTOR:
    904     {
    905       out << arg_name << ".resize(" << arg_value_name
    906           << ".vector_value_size());\n";
    907       out << "for (int i = 0; i <" << arg_value_name
    908           << ".vector_value_size(); i++) {\n";
    909       out.indent();
    910       GenerateDriverImplForTypedVariable(out, val.vector_value(0),
    911                                          arg_name + "[i]",
    912                                          arg_value_name + ".vector_value(i)");
    913       out.unindent();
    914       out << "}\n";
    915       break;
    916     }
    917     case TYPE_ARRAY:
    918     {
    919       out << "for (int i = 0; i < " << arg_value_name
    920           << ".vector_value_size(); i++) {\n";
    921       out.indent();
    922       GenerateDriverImplForTypedVariable(out, val.vector_value(0),
    923                                          arg_name + "[i]",
    924                                          arg_value_name + ".vector_value(i)");
    925       out.unindent();
    926       out << "}\n";
    927       break;
    928     }
    929     case TYPE_STRUCT:
    930     {
    931       if (val.has_predefined_type()) {
    932         string func_name = "MessageTo"
    933             + ClearStringWithNameSpaceAccess(val.predefined_type());
    934         out << func_name << "(" << arg_value_name << ", &("
    935             << arg_name << "));\n";
    936       } else {
    937         int struct_index = 0;
    938         for (const auto struct_field : val.struct_value()) {
    939           string struct_field_name = arg_name + "." + struct_field.name();
    940           string struct_field_value_name = arg_value_name + ".struct_value("
    941               + std::to_string(struct_index) + ")";
    942           GenerateDriverImplForTypedVariable(out, struct_field,
    943                                              struct_field_name,
    944                                              struct_field_value_name);
    945           struct_index++;
    946         }
    947       }
    948       break;
    949     }
    950     case TYPE_UNION:
    951     {
    952       if (val.has_predefined_type()) {
    953         string func_name = "MessageTo"
    954             + ClearStringWithNameSpaceAccess(val.predefined_type());
    955         out << func_name << "(" << arg_value_name << ", &(" << arg_name
    956             << "));\n";
    957       } else {
    958         int union_index = 0;
    959         for (const auto union_field : val.union_value()) {
    960           string union_field_name = arg_name + "." + union_field.name();
    961           string union_field_value_name = arg_value_name + ".union_value("
    962               + std::to_string(union_index) + ")";
    963           GenerateDriverImplForTypedVariable(out, union_field, union_field_name,
    964                                              union_field_value_name);
    965           union_index++;
    966         }
    967       }
    968       break;
    969     }
    970     case TYPE_HIDL_CALLBACK:
    971     {
    972       string type_name = val.predefined_type();
    973       ReplaceSubString(type_name, "::", "_");
    974 
    975       out << arg_name << " = VtsFuzzerCreateVts" << type_name
    976           << "(callback_socket_name);\n";
    977       out << "static_cast<" << "Vts" + type_name << "*>(" << arg_name
    978           << ".get())->Register(" << arg_value_name << ");\n";
    979       break;
    980     }
    981     case TYPE_HANDLE:
    982     {
    983       out << "if (" << arg_value_name << ".has_handle_value()) {\n";
    984       out.indent();
    985       out << "native_handle_t* handle = native_handle_create(" << arg_value_name
    986           << ".handle_value().num_fds(), " << arg_value_name
    987           << ".handle_value().num_ints());\n";
    988       out << "if (!handle) {\n";
    989       out.indent();
    990       out << "cerr << \"Failed to create handle. \" << endl;\n";
    991       out << "exit(-1);\n";
    992       out.unindent();
    993       out << "}\n";
    994       out << "for (int fd_index = 0; fd_index < " << arg_value_name
    995           << ".handle_value().num_fds() + " << arg_value_name
    996           << ".handle_value().num_ints(); fd_index++) {\n";
    997       out.indent();
    998       out << "if (fd_index < " << arg_value_name
    999           << ".handle_value().num_fds()) {\n";
   1000       out.indent();
   1001       out << "FdMessage fd_val = " << arg_value_name
   1002           << ".handle_value().fd_val(fd_index);\n";
   1003       out << "string file_name = fd_val.file_name();\n";
   1004       out << "switch (fd_val.type()) {\n";
   1005       out.indent();
   1006       out << "case FdType::FILE_TYPE:\n";
   1007       out << "{\n";
   1008       out.indent();
   1009       // Create the parent path recursively if not exist.
   1010       out << "size_t pre = 0; size_t pos = 0;\n";
   1011       out << "string dir;\n";
   1012       out << "struct stat st;\n";
   1013       out << "while((pos=file_name.find_first_of('/', pre)) "
   1014           << "!= string::npos){\n";
   1015       out.indent();
   1016       out << "dir = file_name.substr(0, pos++);\n";
   1017       out << "pre = pos;\n";
   1018       out << "if(dir.size() == 0) continue; // ignore leading /\n";
   1019       out << "if (stat(dir.c_str(), &st) == -1) {\n";
   1020       out << "cout << \" Creating dir: \" << dir << endl;\n";
   1021       out.indent();
   1022       out << "mkdir(dir.c_str(), 0700);\n";
   1023       out.unindent();
   1024       out << "}\n";
   1025       out.unindent();
   1026       out << "}\n";
   1027       out << "int fd = open(file_name.c_str(), "
   1028           << "fd_val.flags() | O_CREAT, fd_val.mode());\n";
   1029       out << "if (fd == -1) {\n";
   1030       out.indent();
   1031       out << "cout << \"Failed to open file: \" << file_name << \" error: \" "
   1032           << "<< errno << endl;\n";
   1033       out << "exit (-1);\n";
   1034       out.unindent();
   1035       out << "}\n";
   1036       out << "handle->data[fd_index] = fd;\n";
   1037       out << "break;\n";
   1038       out.unindent();
   1039       out << "}\n";
   1040       out << "case FdType::DIR_TYPE:\n";
   1041       out << "{\n";
   1042       out.indent();
   1043       out << "struct stat st;\n";
   1044       out << "if (!stat(file_name.c_str(), &st)) {\n";
   1045       out.indent();
   1046       out << "mkdir(file_name.c_str(), fd_val.mode());\n";
   1047       out.unindent();
   1048       out << "}\n";
   1049       out << "handle->data[fd_index] = open(file_name.c_str(), O_DIRECTORY, "
   1050           << "fd_val.mode());\n";
   1051       out << "break;\n";
   1052       out.unindent();
   1053       out << "}\n";
   1054       out << "case FdType::DEV_TYPE:\n";
   1055       out << "{\n";
   1056       out.indent();
   1057       out << "if(file_name == \"/dev/ashmem\") {\n";
   1058       out.indent();
   1059       out << "handle->data[fd_index] = ashmem_create_region(\"SharedMemory\", "
   1060           << "fd_val.memory().size());\n";
   1061       out.unindent();
   1062       out << "}\n";
   1063       out << "break;\n";
   1064       out.unindent();
   1065       out << "}\n";
   1066       out << "case FdType::PIPE_TYPE:\n";
   1067       out << "case FdType::SOCKET_TYPE:\n";
   1068       out << "case FdType::LINK_TYPE:\n";
   1069       out << "{\n";
   1070       out.indent();
   1071       out << "cout << \"Not supported yet. \" << endl;\n";
   1072       out << "break;\n";
   1073       out.unindent();
   1074       out << "}\n";
   1075       out.unindent();
   1076       out << "}\n";
   1077       out.unindent();
   1078       out << "} else {\n";
   1079       out.indent();
   1080       out << "handle->data[fd_index] = " << arg_value_name
   1081           << ".handle_value().int_val(fd_index -" << arg_value_name
   1082           << ".handle_value().num_fds());\n";
   1083       out.unindent();
   1084       out << "}\n";
   1085       out.unindent();
   1086       out << "}\n";
   1087       out << arg_name << " = handle;\n";
   1088       out.unindent();
   1089       out << "} else {\n";
   1090       out.indent();
   1091       out << arg_name << " = nullptr;\n";
   1092       out.unindent();
   1093       out << "}\n";
   1094       break;
   1095     }
   1096     case TYPE_HIDL_INTERFACE:
   1097     {
   1098       out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
   1099       break;
   1100     }
   1101     case TYPE_HIDL_MEMORY:
   1102     {
   1103       out << "sp<::android::hidl::allocator::V1_0::IAllocator> ashmemAllocator"
   1104           << " = ::android::hidl::allocator::V1_0::IAllocator::getService(\""
   1105           << "ashmem\");\n";
   1106       out << "if (ashmemAllocator == nullptr) {\n";
   1107       out.indent();
   1108       out << "cerr << \"Failed to get ashmemAllocator! \" << endl;\n";
   1109       out << "exit(-1);\n";
   1110       out.unindent();
   1111       out << "}\n";
   1112       // TODO(zhuoyao): initialize memory with recorded contents.
   1113       out << "auto res = ashmemAllocator->allocate(" << arg_value_name
   1114           << ".hidl_memory_value().size(), [&](bool success, "
   1115           << "const hardware::hidl_memory& memory) {\n";
   1116       out.indent();
   1117       out << "if (!success) {\n";
   1118       out.indent();
   1119       out << "cerr << \"Failed to allocate memory! \" << endl;\n";
   1120       out << arg_name << " = ::android::hardware::hidl_memory();\n";
   1121       out << "return;\n";
   1122       out.unindent();
   1123       out << "}\n";
   1124       out << arg_name << " = memory;\n";
   1125       out.unindent();
   1126       out << "});\n";
   1127       break;
   1128     }
   1129     case TYPE_POINTER:
   1130     {
   1131       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
   1132       break;
   1133     }
   1134     case TYPE_FMQ_SYNC:
   1135     {
   1136       if (arg_name.find("->") != std::string::npos) {
   1137         cout << "Nested structure with fmq is not supported yet." << endl;
   1138       } else {
   1139         std::string element_type =
   1140             GetCppVariableType(val.fmq_value(0), nullptr);
   1141         std::string queue_name = arg_name + "_sync_q";
   1142         // TODO(zhuoyao): consider record and use the queue capacity.
   1143         out << "::android::hardware::MessageQueue<" << element_type
   1144             << ", ::android::hardware::kSynchronizedReadWrite> " << queue_name
   1145             << "(1024);\n";
   1146         out << "for (int i = 0; i < (int)" << arg_value_name
   1147             << ".fmq_value_size(); i++) {\n";
   1148         out.indent();
   1149         std::string fmq_item_name = queue_name + "_item";
   1150         out << element_type << " " << fmq_item_name << ";\n";
   1151         GenerateDriverImplForTypedVariable(out, val.fmq_value(0), fmq_item_name,
   1152                                            arg_value_name + ".fmq_value(i)");
   1153         out << queue_name << ".write(&" << fmq_item_name << ");\n";
   1154         out.unindent();
   1155         out << "}\n";
   1156         out << GetCppVariableType(val, nullptr) << " " << arg_name << "(*"
   1157             << queue_name << ".getDesc());\n";
   1158       }
   1159       break;
   1160     }
   1161     case TYPE_FMQ_UNSYNC:
   1162     {
   1163       if (arg_name.find("->") != std::string::npos) {
   1164         cout << "Nested structure with fmq is not supported yet." << endl;
   1165       } else {
   1166         std::string element_type =
   1167             GetCppVariableType(val.fmq_value(0), nullptr);
   1168         std::string queue_name = arg_name + "_unsync_q";
   1169         // TODO(zhuoyao): consider record and use the queue capacity.
   1170         out << "::android::hardware::MessageQueue<" << element_type << ", "
   1171             << "::android::hardware::kUnsynchronizedWrite> " << queue_name
   1172             << "(1024);\n";
   1173         out << "for (int i = 0; i < (int)" << arg_value_name
   1174             << ".fmq_value_size(); i++) {\n";
   1175         out.indent();
   1176         std::string fmq_item_name = queue_name + "_item";
   1177         out << element_type << " " << fmq_item_name << ";\n";
   1178         GenerateDriverImplForTypedVariable(out, val.fmq_value(0), fmq_item_name,
   1179                                            arg_value_name + ".fmq_value(i)");
   1180         out << queue_name << ".write(&" << fmq_item_name << ");\n";
   1181         out.unindent();
   1182         out << "}\n";
   1183         out << GetCppVariableType(val, nullptr) << " " << arg_name << "(*"
   1184             << queue_name << ".getDesc());\n";
   1185       }
   1186       break;
   1187     }
   1188     case TYPE_REF:
   1189     {
   1190       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
   1191       break;
   1192     }
   1193     default:
   1194     {
   1195       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
   1196       exit(-1);
   1197     }
   1198   }
   1199 }
   1200 
   1201 // TODO(zhuoyao): Verify results based on verification rules instead of perform
   1202 // an exact match.
   1203 void HalHidlCodeGen::GenerateVerificationFunctionImpl(Formatter& out,
   1204     const ComponentSpecificationMessage& message,
   1205     const string& fuzzer_extended_class_name) {
   1206   if (message.component_name() != "types") {
   1207     // Generate the main profiler function.
   1208     out << "\nbool " << fuzzer_extended_class_name;
   1209     out.indent();
   1210     out << "::VerifyResults(const FunctionSpecificationMessage& "
   1211            "expected_result __attribute__((__unused__)),"
   1212         << "\n";
   1213     out << "const FunctionSpecificationMessage& actual_result "
   1214            "__attribute__((__unused__))) {\n";
   1215     for (const FunctionSpecificationMessage api : message.interface().api()) {
   1216       out << "if (!strcmp(actual_result.name().c_str(), \"" << api.name()
   1217           << "\")) {\n";
   1218       out.indent();
   1219       out << "if (actual_result.return_type_hidl_size() != "
   1220           << "expected_result.return_type_hidl_size() "
   1221           << ") { return false; }\n";
   1222       for (int i = 0; i < api.return_type_hidl_size(); i++) {
   1223         std::string expected_result = "expected_result.return_type_hidl("
   1224             + std::to_string(i) + ")";
   1225         std::string actual_result = "actual_result.return_type_hidl("
   1226             + std::to_string(i) + ")";
   1227         GenerateVerificationCodeForTypedVariable(out, api.return_type_hidl(i),
   1228                                                  expected_result,
   1229                                                  actual_result);
   1230       }
   1231       out << "return true;\n";
   1232       out.unindent();
   1233       out << "}\n";
   1234     }
   1235     out << "return false;\n";
   1236     out.unindent();
   1237     out << "}\n\n";
   1238   }
   1239 }
   1240 
   1241 void HalHidlCodeGen::GenerateVerificationCodeForTypedVariable(Formatter& out,
   1242     const VariableSpecificationMessage& val, const string& expected_result,
   1243     const string& actual_result) {
   1244   switch (val.type()) {
   1245     case TYPE_SCALAR:
   1246     {
   1247       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
   1248           << "() != " << expected_result << ".scalar_value()."
   1249           << val.scalar_type() << "()) { return false; }\n";
   1250       break;
   1251     }
   1252     case TYPE_STRING:
   1253     {
   1254       out << "if (strcmp(" << actual_result
   1255           << ".string_value().message().c_str(), " << expected_result
   1256           << ".string_value().message().c_str())!= 0)" << "{ return false; }\n";
   1257       break;
   1258     }
   1259     case TYPE_ENUM:
   1260     {
   1261       if (val.has_predefined_type()) {
   1262         string func_name = "Verify"
   1263             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1264         out << "if(!" << func_name << "(" << expected_result << ", "
   1265             << actual_result << ")) { return false; }\n";
   1266       } else {
   1267         out << "if (" << actual_result << ".scalar_value()."
   1268             << val.enum_value().scalar_type() << "() != " << expected_result
   1269             << ".scalar_value()." << val.enum_value().scalar_type()
   1270             << "()) { return false; }\n";
   1271       }
   1272       break;
   1273     }
   1274     case TYPE_MASK:
   1275     {
   1276       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
   1277           << "() != " << expected_result << ".scalar_value()."
   1278           << val.scalar_type() << "()) { return false; }\n";
   1279       break;
   1280     }
   1281     case TYPE_VECTOR:
   1282     {
   1283       out << "if (" << actual_result << ".vector_value_size() != "
   1284           << expected_result << ".vector_value_size()) {\n";
   1285       out.indent();
   1286       out << "cerr << \"Verification failed for vector size. expected: \" << "
   1287              << expected_result << ".vector_value_size() << \" actual: \" << "
   1288              << actual_result << ".vector_value_size();\n";
   1289       out << "return false;\n";
   1290       out.unindent();
   1291       out << "}\n";
   1292       out << "for (int i = 0; i <" << expected_result
   1293           << ".vector_value_size(); i++) {\n";
   1294       out.indent();
   1295       GenerateVerificationCodeForTypedVariable(
   1296           out, val.vector_value(0), expected_result + ".vector_value(i)",
   1297           actual_result + ".vector_value(i)");
   1298       out.unindent();
   1299       out << "}\n";
   1300       break;
   1301     }
   1302     case TYPE_ARRAY:
   1303     {
   1304       out << "if (" << actual_result << ".vector_value_size() != "
   1305           << expected_result << ".vector_value_size()) {\n";
   1306       out.indent();
   1307       out << "cerr << \"Verification failed for vector size. expected: \" << "
   1308           << expected_result << ".vector_value_size() << \" actual: \" << "
   1309           << actual_result << ".vector_value_size();\n";
   1310       out << "return false;\n";
   1311       out.unindent();
   1312       out << "}\n";
   1313       out << "for (int i = 0; i < " << expected_result
   1314           << ".vector_value_size(); i++) {\n";
   1315       out.indent();
   1316       GenerateVerificationCodeForTypedVariable(
   1317           out, val.vector_value(0), expected_result + ".vector_value(i)",
   1318           actual_result + ".vector_value(i)");
   1319       out.unindent();
   1320       out << "}\n";
   1321       break;
   1322     }
   1323     case TYPE_STRUCT:
   1324     {
   1325       if (val.has_predefined_type()) {
   1326         string func_name = "Verify"
   1327             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1328         out << "if (!" << func_name << "(" << expected_result << ", "
   1329             << actual_result << ")) { return false; }\n";
   1330       } else {
   1331         for (int i = 0; i < val.struct_value_size(); i++) {
   1332           string struct_field_actual_result = actual_result + ".struct_value("
   1333               + std::to_string(i) + ")";
   1334           string struct_field_expected_result = expected_result
   1335               + ".struct_value(" + std::to_string(i) + ")";
   1336           GenerateVerificationCodeForTypedVariable(out, val.struct_value(i),
   1337                                                    struct_field_expected_result,
   1338                                                    struct_field_actual_result);
   1339         }
   1340       }
   1341       break;
   1342     }
   1343     case TYPE_UNION:
   1344     {
   1345       if (val.has_predefined_type()) {
   1346         string func_name = "Verify"
   1347             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1348         out << "if (!" << func_name << "(" << expected_result << ", "
   1349             << actual_result << ")) {return false; }\n";
   1350       } else {
   1351         for (int i = 0; i < val.union_value_size(); i++) {
   1352           string union_field_actual_result = actual_result + ".union_value("
   1353               + std::to_string(i) + ")";
   1354           string union_field_expected_result = expected_result + ".union_value("
   1355               + std::to_string(i) + ")";
   1356           GenerateVerificationCodeForTypedVariable(out, val.union_value(i),
   1357                                                    union_field_expected_result,
   1358                                                    union_field_actual_result);
   1359         }
   1360       }
   1361       break;
   1362     }
   1363     case TYPE_HIDL_CALLBACK:
   1364     {
   1365       out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
   1366       break;
   1367     }
   1368     case TYPE_HANDLE:
   1369     {
   1370       out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
   1371       break;
   1372     }
   1373     case TYPE_HIDL_INTERFACE:
   1374     {
   1375       out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
   1376       break;
   1377     }
   1378     case TYPE_HIDL_MEMORY:
   1379     {
   1380       out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
   1381       break;
   1382     }
   1383     case TYPE_POINTER:
   1384     {
   1385       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
   1386       break;
   1387     }
   1388     case TYPE_FMQ_SYNC:
   1389     {
   1390       out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
   1391       break;
   1392     }
   1393     case TYPE_FMQ_UNSYNC:
   1394     {
   1395       out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
   1396       break;
   1397     }
   1398     case TYPE_REF:
   1399     {
   1400       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
   1401       break;
   1402     }
   1403     default:
   1404     {
   1405       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
   1406       exit(-1);
   1407     }
   1408   }
   1409 }
   1410 
   1411 void HalHidlCodeGen::GenerateVerificationDeclForAttribute(Formatter& out,
   1412     const VariableSpecificationMessage& attribute) {
   1413   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1414     // Recursively generate verification method implementation for all sub_types.
   1415     for (const auto sub_struct : attribute.sub_struct()) {
   1416       GenerateVerificationDeclForAttribute(out, sub_struct);
   1417     }
   1418     for (const auto sub_union : attribute.sub_union()) {
   1419       GenerateVerificationDeclForAttribute(out, sub_union);
   1420     }
   1421   }
   1422   std::string func_name = "bool Verify"
   1423       + ClearStringWithNameSpaceAccess(attribute.name());
   1424   out << func_name << "(const VariableSpecificationMessage& expected_result, "
   1425       << "const VariableSpecificationMessage& actual_result);\n";
   1426 }
   1427 
   1428 void HalHidlCodeGen::GenerateVerificationImplForAttribute(Formatter& out,
   1429     const VariableSpecificationMessage& attribute) {
   1430   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1431     // Recursively generate verification method implementation for all sub_types.
   1432     for (const auto sub_struct : attribute.sub_struct()) {
   1433       GenerateVerificationImplForAttribute(out, sub_struct);
   1434     }
   1435     for (const auto sub_union : attribute.sub_union()) {
   1436       GenerateVerificationImplForAttribute(out, sub_union);
   1437     }
   1438   }
   1439   std::string func_name = "bool Verify"
   1440       + ClearStringWithNameSpaceAccess(attribute.name());
   1441   out << func_name << "(const VariableSpecificationMessage& expected_result "
   1442                       "__attribute__((__unused__)), "
   1443       << "const VariableSpecificationMessage& actual_result "
   1444          "__attribute__((__unused__))){\n";
   1445   out.indent();
   1446   GenerateVerificationCodeForTypedVariable(out, attribute, "expected_result",
   1447                                            "actual_result");
   1448   out << "return true;\n";
   1449   out.unindent();
   1450   out << "}\n\n";
   1451 }
   1452 
   1453 // TODO(zhuoyao): consider to generalize the pattern for
   1454 // Verification/SetResult/DriverImpl.
   1455 void HalHidlCodeGen::GenerateSetResultCodeForTypedVariable(Formatter& out,
   1456     const VariableSpecificationMessage& val, const string& result_msg,
   1457     const string& result_value) {
   1458   switch (val.type()) {
   1459     case TYPE_SCALAR:
   1460     {
   1461       out << result_msg << "->set_type(TYPE_SCALAR);\n";
   1462       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
   1463           << "\");\n";
   1464       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
   1465           << "(" << result_value << ");\n";
   1466       break;
   1467     }
   1468     case TYPE_STRING:
   1469     {
   1470       out << result_msg << "->set_type(TYPE_STRING);\n";
   1471       out << result_msg << "->mutable_string_value()->set_message" << "("
   1472           << result_value << ".c_str());\n";
   1473       out << result_msg << "->mutable_string_value()->set_length" << "("
   1474           << result_value << ".size());\n";
   1475       break;
   1476     }
   1477     case TYPE_ENUM:
   1478     {
   1479       out << result_msg << "->set_type(TYPE_ENUM);\n";
   1480       if (val.has_predefined_type()) {
   1481         string func_name = "SetResult"
   1482             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1483         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1484       } else {
   1485         const string scalar_type = val.enum_value().scalar_type();
   1486         out << result_msg << "->set_scalar_type(\"" << scalar_type << "\");\n";
   1487         out << result_msg << "->mutable_scalar_value()->set_" << scalar_type
   1488             << "(static_cast<" << scalar_type << ">(" << result_value
   1489             << "));\n";
   1490       }
   1491       break;
   1492     }
   1493     case TYPE_MASK:
   1494     {
   1495       out << result_msg << "->set_type(TYPE_MASK);\n";
   1496       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
   1497           << "\");\n";
   1498       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
   1499           << "(" << result_value << ");\n";
   1500       break;
   1501     }
   1502     case TYPE_VECTOR:
   1503     {
   1504       out << result_msg << "->set_type(TYPE_VECTOR);\n";
   1505       out << result_msg << "->set_vector_size(" << result_value
   1506           << ".size());\n";
   1507       out << "for (int i = 0; i < (int)" << result_value << ".size(); i++) {\n";
   1508       out.indent();
   1509       string vector_element_name = result_msg + "_vector_i";
   1510       out << "auto *" << vector_element_name << " = " << result_msg
   1511           << "->add_vector_value();\n";
   1512       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
   1513                                             vector_element_name,
   1514                                             result_value + "[i]");
   1515       out.unindent();
   1516       out << "}\n";
   1517       break;
   1518     }
   1519     case TYPE_ARRAY:
   1520     {
   1521       out << result_msg << "->set_type(TYPE_ARRAY);\n";
   1522       out << result_msg << "->set_vector_size(" << val.vector_value_size()
   1523           << ");\n";
   1524       out << "for (int i = 0; i < " << val.vector_value_size() << "; i++) {\n";
   1525       out.indent();
   1526       string array_element_name = result_msg + "_array_i";
   1527       out << "auto *" << array_element_name << " = " << result_msg
   1528           << "->add_vector_value();\n";
   1529       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
   1530                                             array_element_name,
   1531                                             result_value + "[i]");
   1532       out.unindent();
   1533       out << "}\n";
   1534       break;
   1535     }
   1536     case TYPE_STRUCT:
   1537     {
   1538       out << result_msg << "->set_type(TYPE_STRUCT);\n";
   1539       if (val.has_predefined_type()) {
   1540         string func_name = "SetResult"
   1541             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1542         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1543       } else {
   1544         for (const auto struct_field : val.struct_value()) {
   1545           string struct_field_name = result_msg + "_" + struct_field.name();
   1546           out << "auto *" << struct_field_name << " = " << result_msg
   1547               << "->add_struct_value();\n";
   1548           GenerateSetResultCodeForTypedVariable(
   1549               out, struct_field, struct_field_name,
   1550               result_value + "." + struct_field.name());
   1551           if (struct_field.has_name()) {
   1552             out << struct_field_name << "->set_name(\""
   1553                 << struct_field.name() << "\");\n";
   1554           }
   1555         }
   1556       }
   1557       break;
   1558     }
   1559     case TYPE_UNION:
   1560     {
   1561       out << result_msg << "->set_type(TYPE_UNION);\n";
   1562       if (val.has_predefined_type()) {
   1563         string func_name = "SetResult"
   1564             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1565         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1566       } else {
   1567         for (const auto union_field : val.union_value()) {
   1568           string union_field_name = result_msg + "_" + union_field.name();
   1569           out << "auto *" << union_field_name << " = " << result_msg
   1570               << "->add_union_value();\n";
   1571           GenerateSetResultCodeForTypedVariable(
   1572               out, union_field, union_field_name,
   1573               result_value + "." + union_field.name());
   1574         }
   1575       }
   1576       break;
   1577     }
   1578     case TYPE_HIDL_CALLBACK:
   1579     {
   1580       out << result_msg << "->set_type(TYPE_HIDL_CALLBACK);\n";
   1581       out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
   1582       break;
   1583     }
   1584     case TYPE_HANDLE:
   1585     {
   1586       out << result_msg << "->set_type(TYPE_HANDLE);\n";
   1587       out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
   1588       break;
   1589     }
   1590     case TYPE_HIDL_INTERFACE:
   1591     {
   1592       out << result_msg << "->set_type(TYPE_HIDL_INTERFACE);\n";
   1593       if (!val.has_predefined_type()) {
   1594         cerr << __func__ << ":" << __LINE__
   1595              << " HIDL interface is a return type"
   1596              << "but predefined_type is unset." << endl;
   1597         exit(-1);
   1598       }
   1599       out << result_msg << "->set_predefined_type(\"" << val.predefined_type()
   1600           << "\");\n";
   1601       out << "if (" << result_value << " != nullptr) {\n";
   1602       out.indent();
   1603       out << result_value << "->incStrong(" << result_value << ".get());\n";
   1604       out << result_msg << "->set_hidl_interface_pointer("
   1605           << "reinterpret_cast<uintptr_t>(" << result_value << ".get()));\n";
   1606       out.unindent();
   1607       out << "} else {\n";
   1608       out.indent();
   1609       out << result_msg << "->set_hidl_interface_pointer(0);\n";
   1610       out.unindent();
   1611       out << "}\n";
   1612       break;
   1613     }
   1614     case TYPE_HIDL_MEMORY:
   1615     {
   1616       out << result_msg << "->set_type(TYPE_HIDL_MEMORY);\n";
   1617       out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
   1618       break;
   1619     }
   1620     case TYPE_POINTER:
   1621     {
   1622       out << result_msg << "->set_type(TYPE_POINTER);\n";
   1623       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
   1624       break;
   1625     }
   1626     case TYPE_FMQ_SYNC:
   1627     {
   1628       out << result_msg << "->set_type(TYPE_FMQ_SYNC);\n";
   1629       out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
   1630       break;
   1631     }
   1632     case TYPE_FMQ_UNSYNC:
   1633     {
   1634       out << result_msg << "->set_type(TYPE_FMQ_UNSYNC);\n";
   1635       out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
   1636       break;
   1637     }
   1638     case TYPE_REF:
   1639     {
   1640       out << result_msg << "->set_type(TYPE_REF);\n";
   1641       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
   1642       break;
   1643     }
   1644     default:
   1645     {
   1646       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
   1647       exit(-1);
   1648     }
   1649   }
   1650 }
   1651 
   1652 void HalHidlCodeGen::GenerateSetResultDeclForAttribute(Formatter& out,
   1653     const VariableSpecificationMessage& attribute) {
   1654   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1655     // Recursively generate SetResult method implementation for all sub_types.
   1656     for (const auto sub_struct : attribute.sub_struct()) {
   1657       GenerateSetResultDeclForAttribute(out, sub_struct);
   1658     }
   1659     for (const auto sub_union : attribute.sub_union()) {
   1660       GenerateSetResultDeclForAttribute(out, sub_union);
   1661     }
   1662   }
   1663   string func_name = "void SetResult"
   1664       + ClearStringWithNameSpaceAccess(attribute.name());
   1665   out << func_name << "(VariableSpecificationMessage* result_msg, "
   1666       << attribute.name() << " result_value);\n";
   1667 }
   1668 
   1669 void HalHidlCodeGen::GenerateSetResultImplForAttribute(Formatter& out,
   1670     const VariableSpecificationMessage& attribute) {
   1671   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1672     // Recursively generate SetResult method implementation for all sub_types.
   1673     for (const auto sub_struct : attribute.sub_struct()) {
   1674       GenerateSetResultImplForAttribute(out, sub_struct);
   1675     }
   1676     for (const auto sub_union : attribute.sub_union()) {
   1677       GenerateSetResultImplForAttribute(out, sub_union);
   1678     }
   1679   }
   1680   string func_name = "void SetResult"
   1681       + ClearStringWithNameSpaceAccess(attribute.name());
   1682   out << func_name << "(VariableSpecificationMessage* result_msg, "
   1683       << attribute.name() << " result_value __attribute__((__unused__))){\n";
   1684   out.indent();
   1685   GenerateSetResultCodeForTypedVariable(out, attribute, "result_msg",
   1686                                         "result_value");
   1687   out.unindent();
   1688   out << "}\n\n";
   1689 }
   1690 
   1691 void HalHidlCodeGen::GenerateAllFunctionDeclForAttribute(Formatter& out,
   1692     const VariableSpecificationMessage& attribute) {
   1693   GenerateDriverDeclForAttribute(out, attribute);
   1694   GenerateRandomFunctionDeclForAttribute(out, attribute);
   1695   GenerateVerificationDeclForAttribute(out, attribute);
   1696   GenerateSetResultDeclForAttribute(out, attribute);
   1697 }
   1698 
   1699 void HalHidlCodeGen::GenerateAllFunctionImplForAttribute(Formatter& out,
   1700     const VariableSpecificationMessage& attribute) {
   1701   GenerateDriverImplForAttribute(out, attribute);
   1702   GenerateRandomFunctionImplForAttribute(out, attribute);
   1703   GenerateVerificationImplForAttribute(out, attribute);
   1704   GenerateSetResultImplForAttribute(out, attribute);
   1705 }
   1706 
   1707 bool HalHidlCodeGen::CanElideCallback(
   1708     const FunctionSpecificationMessage& func_msg) {
   1709   // Can't elide callback for void or tuple-returning methods
   1710   if (func_msg.return_type_hidl_size() != 1) {
   1711     return false;
   1712   }
   1713   const VariableType& type = func_msg.return_type_hidl(0).type();
   1714   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
   1715     return false;
   1716   }
   1717   return isElidableType(type);
   1718 }
   1719 
   1720 bool HalHidlCodeGen::isElidableType(const VariableType& type) {
   1721   if (type == TYPE_SCALAR || type == TYPE_ENUM || type == TYPE_MASK
   1722       || type == TYPE_POINTER || type == TYPE_HIDL_INTERFACE
   1723       || type == TYPE_VOID) {
   1724     return true;
   1725   }
   1726   return false;
   1727 }
   1728 
   1729 bool HalHidlCodeGen::isConstType(const VariableType& type) {
   1730   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF ||
   1731       type == TYPE_HIDL_INTERFACE) {
   1732     return true;
   1733   }
   1734   if (isElidableType(type)) {
   1735     return false;
   1736   }
   1737   return true;
   1738 }
   1739 
   1740 }  // namespace vts
   1741 }  // namespace android
   1742