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::GenerateCppBodyCallbackFunction(Formatter& out,
     40     const ComponentSpecificationMessage& message,
     41     const string& /*fuzzer_extended_class_name*/) {
     42   if (endsWith(message.component_name(), "Callback")) {
     43     out << "\n";
     44     FQName component_fq_name = GetFQName(message);
     45     for (const auto& api : message.interface().api()) {
     46       // Generate return statement.
     47       if (CanElideCallback(api)) {
     48         out << "::android::hardware::Return<"
     49             << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
     50       } else {
     51         out << "::android::hardware::Return<void> ";
     52       }
     53       // Generate function call.
     54       string full_method_name = "Vts_" + component_fq_name.tokenName() + "::"
     55           + api.name();
     56       out << full_method_name << "(\n";
     57       out.indent();
     58       for (int index = 0; index < api.arg_size(); index++) {
     59         const auto& arg = api.arg(index);
     60         if (!isConstType(arg.type())) {
     61           out << GetCppVariableType(arg, &message);
     62         } else {
     63           out << GetCppVariableType(arg, &message, true);
     64         }
     65         out << " arg" << index;
     66         if (index != (api.arg_size() - 1))
     67           out << ",\n";
     68       }
     69       if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
     70         out << ") {" << "\n";
     71       } else {  // handle the case of callbacks.
     72         out << (api.arg_size() != 0 ? ", " : "");
     73         out << "std::function<void(";
     74         for (int index = 0; index < api.return_type_hidl_size(); index++) {
     75           const auto& return_val = api.return_type_hidl(index);
     76           if (!isConstType(return_val.type())) {
     77             out << GetCppVariableType(return_val, &message);
     78           } else {
     79             out << GetCppVariableType(return_val, &message, true);
     80           }
     81           out << " arg" << index;
     82           if (index != (api.return_type_hidl_size() - 1))
     83             out << ",";
     84         }
     85         out << ")>) {" << "\n";
     86       }
     87       out << "cout << \"" << api.name() << " called\" << endl;" << "\n";
     88       out << "AndroidSystemCallbackRequestMessage callback_message;" << "\n";
     89       out << "callback_message.set_id(GetCallbackID(\"" << api.name() << "\"));" << "\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       if (api.return_type_hidl_size() == 0
    101           || api.return_type_hidl(0).type() == TYPE_VOID) {
    102         out << "return ::android::hardware::Void();" << "\n";
    103       } else {
    104         out << "return hardware::Status::ok();" << "\n";
    105       }
    106       out.unindent();
    107       out << "}" << "\n";
    108       out << "\n";
    109     }
    110 
    111     string component_name_token = "Vts_" + component_fq_name.tokenName();
    112     out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
    113         << component_name_token << "(const string& callback_socket_name)";
    114     out << " {" << "\n";
    115     out.indent();
    116     out << "static sp<" << component_fq_name.cppName() << "> result;\n";
    117     out << "result = new " << component_name_token << "(callback_socket_name);"
    118         << "\n";
    119     out << "return result;\n";
    120     out.unindent();
    121     out << "}" << "\n" << "\n";
    122   }
    123 }
    124 
    125 void HalHidlCodeGen::GenerateScalarTypeInC(Formatter& out, const string& type) {
    126   if (type == "bool_t") {
    127     out << "bool";
    128   } else if (type == "int8_t" ||
    129              type == "uint8_t" ||
    130              type == "int16_t" ||
    131              type == "uint16_t" ||
    132              type == "int32_t" ||
    133              type == "uint32_t" ||
    134              type == "int64_t" ||
    135              type == "uint64_t" ||
    136              type == "size_t") {
    137     out << type;
    138   } else if (type == "float_t") {
    139     out << "float";
    140   } else if (type == "double_t") {
    141     out << "double";
    142   } else if (type == "char_pointer") {
    143     out << "char*";
    144   } else if (type == "void_pointer") {
    145     out << "void*";
    146   } else {
    147     cerr << __func__ << ":" << __LINE__
    148          << " unsupported scalar type " << type << "\n";
    149     exit(-1);
    150   }
    151 }
    152 
    153 
    154 void HalHidlCodeGen::GenerateCppBodyFuzzFunction(
    155     Formatter& out, const ComponentSpecificationMessage& /*message*/,
    156     const string& fuzzer_extended_class_name) {
    157     out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
    158     out << "    FunctionSpecificationMessage* func_msg," << "\n";
    159     out << "    void** result, const string& callback_socket_name) {\n";
    160     out.indent();
    161     out << "return true;\n";
    162     out.unindent();
    163     out << "}\n";
    164 }
    165 
    166 void HalHidlCodeGen::GenerateDriverFunctionImpl(Formatter& out,
    167     const ComponentSpecificationMessage& message,
    168     const string& fuzzer_extended_class_name) {
    169   if (message.component_name() != "types"
    170       && !endsWith(message.component_name(), "Callback")) {
    171     out << "bool " << fuzzer_extended_class_name << "::CallFunction("
    172         << "const FunctionSpecificationMessage& func_msg, "
    173         << "const string& callback_socket_name, "
    174         << "FunctionSpecificationMessage* result_msg) {\n";
    175     out.indent();
    176 
    177     out << "const char* func_name = func_msg.name().c_str();" << "\n";
    178     out << "cout << \"Function: \" << __func__ << \" \" << func_name << endl;"
    179         << "\n";
    180 
    181     for (auto const& api : message.interface().api()) {
    182       GenerateDriverImplForMethod(out, message, api);
    183     }
    184 
    185     GenerateDriverImplForReservedMethods(out);
    186 
    187     out << "return false;\n";
    188     out.unindent();
    189     out << "}\n";
    190   }
    191 }
    192 
    193 void HalHidlCodeGen::GenerateDriverImplForReservedMethods(Formatter& out) {
    194   // Generate call for reserved method: notifySyspropsChanged.
    195   out << "if (!strcmp(func_name, \"notifySyspropsChanged\")) {\n";
    196   out.indent();
    197 
    198   out << "cout << \"Call notifySyspropsChanged\" << endl;" << "\n";
    199   out << kInstanceVariableName << "->notifySyspropsChanged();\n";
    200   out << "result_msg->set_name(\"notifySyspropsChanged\");\n";
    201   out << "cout << \"called\" << endl;\n";
    202   out << "return true;\n";
    203 
    204   out.unindent();
    205   out << "}\n";
    206   // TODO(zhuoyao): Add generation code for other reserved method,
    207   // e.g interfaceChain
    208 }
    209 
    210 void HalHidlCodeGen::GenerateDriverImplForMethod(Formatter& out,
    211     const ComponentSpecificationMessage& message,
    212     const FunctionSpecificationMessage& func_msg) {
    213   out << "if (!strcmp(func_name, \"" << func_msg.name() << "\")) {\n";
    214   out.indent();
    215   // Process the arguments.
    216   for (int i = 0; i < func_msg.arg_size(); i++) {
    217     const auto& arg = func_msg.arg(i);
    218     string cur_arg_name = "arg" + std::to_string(i);
    219     string var_type;
    220     if (arg.type() == TYPE_ARRAY || arg.type() == TYPE_VECTOR) {
    221       var_type = GetCppVariableType(arg, &message, true);
    222       var_type = var_type.substr(5, var_type.length() - 6);
    223     } else {
    224       var_type = GetCppVariableType(arg, &message);
    225     }
    226     out << var_type << " " << cur_arg_name << ";\n";
    227     if (arg.type() == TYPE_SCALAR) {
    228       out << cur_arg_name << " = 0;\n";
    229     }
    230     GenerateDriverImplForTypedVariable(
    231         out, arg, cur_arg_name, "func_msg.arg(" + std::to_string(i) + ")");
    232   }
    233 
    234   GenerateCodeToStartMeasurement(out);
    235   // may need to check whether the function is actually defined.
    236   out << "cout << \"Call an API\" << endl;" << "\n";
    237   out << "cout << \"local_device = \" << " << kInstanceVariableName << ".get()"
    238       << " << endl;\n";
    239 
    240   // Define the return results and call the HAL function.
    241   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    242     const auto& return_type = func_msg.return_type_hidl(index);
    243     out << GetCppVariableType(return_type, &message) << " result" << index
    244         << ";\n";
    245   }
    246   if (CanElideCallback(func_msg)) {
    247     out << "result0 = ";
    248     GenerateHalFunctionCall(out, message, func_msg);
    249   } else {
    250     GenerateHalFunctionCall(out, message, func_msg);
    251   }
    252 
    253   GenerateCodeToStopMeasurement(out);
    254 
    255   // Set the return results value to the proto message.
    256   out << "result_msg->set_name(\"" << func_msg.name() << "\");\n";
    257   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    258     out << "VariableSpecificationMessage* result_val_" << index << " = "
    259         << "result_msg->add_return_type_hidl();\n";
    260     GenerateSetResultCodeForTypedVariable(out, func_msg.return_type_hidl(index),
    261                                           "result_val_" + std::to_string(index),
    262                                           "result" + std::to_string(index));
    263   }
    264 
    265   out << "cout << \"called\" << endl;\n";
    266   out << "return true;\n";
    267   out.unindent();
    268   out << "}\n";
    269 }
    270 
    271 void HalHidlCodeGen::GenerateHalFunctionCall(Formatter& out,
    272     const ComponentSpecificationMessage& message,
    273     const FunctionSpecificationMessage& func_msg) {
    274   out << kInstanceVariableName << "->" << func_msg.name() << "(";
    275   for (int index = 0; index < func_msg.arg_size(); index++) {
    276     out << "arg" << index;
    277     if (index != (func_msg.arg_size() - 1)) out << ",";
    278   }
    279   if (func_msg.return_type_hidl_size()== 0 || CanElideCallback(func_msg)) {
    280     out << ");\n";
    281   } else {
    282     out << (func_msg.arg_size() != 0 ? ", " : "");
    283     GenerateSyncCallbackFunctionImpl(out, message, func_msg);
    284     out << ");\n";
    285   }
    286 }
    287 
    288 void HalHidlCodeGen::GenerateSyncCallbackFunctionImpl(Formatter& out,
    289     const ComponentSpecificationMessage& message,
    290     const FunctionSpecificationMessage& func_msg) {
    291   out << "[&](";
    292   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    293     const auto& return_val = func_msg.return_type_hidl(index);
    294     if (!isConstType(return_val.type())) {
    295       out << GetCppVariableType(return_val, &message);
    296     } else {
    297       out << GetCppVariableType(return_val, &message, true);
    298     }
    299     out << " arg" << index;
    300     if (index != (func_msg.return_type_hidl_size() - 1)) out << ",";
    301   }
    302   out << "){\n";
    303   out.indent();
    304   out << "cout << \"callback " << func_msg.name() << " called\""
    305       << " << endl;\n";
    306 
    307   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
    308     const auto& return_val = func_msg.return_type_hidl(index);
    309     if (return_val.type() != TYPE_FMQ_SYNC
    310         && return_val.type() != TYPE_FMQ_UNSYNC)
    311       out << "result" << index << " = arg" << index << ";\n";
    312   }
    313   out.unindent();
    314   out << "}";
    315 }
    316 
    317 void HalHidlCodeGen::GenerateCppBodyGetAttributeFunction(
    318     Formatter& out, const ComponentSpecificationMessage& message,
    319     const string& fuzzer_extended_class_name) {
    320   if (message.component_name() != "types" &&
    321       !endsWith(message.component_name(), "Callback")) {
    322     out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
    323     out << "    FunctionSpecificationMessage* func_msg," << "\n";
    324     out << "    void** result) {" << "\n";
    325 
    326     // TOOD: impl
    327     out << "  cerr << \"attribute not found\" << endl;" << "\n";
    328     out << "  return false;" << "\n";
    329     out << "}" << "\n";
    330   }
    331 }
    332 
    333 void HalHidlCodeGen::GenerateClassConstructionFunction(Formatter& out,
    334     const ComponentSpecificationMessage& message,
    335     const string& fuzzer_extended_class_name) {
    336   out << fuzzer_extended_class_name << "() : FuzzerBase(";
    337   if (message.component_name() != "types") {
    338     out << "HAL_HIDL), " << kInstanceVariableName << "()";
    339   } else {
    340     out << "HAL_HIDL)";
    341   }
    342   out << " {}" << "\n";
    343 }
    344 
    345 void HalHidlCodeGen::GenerateHeaderGlobalFunctionDeclarations(Formatter& out,
    346     const ComponentSpecificationMessage& message) {
    347   if (message.component_name() != "types"
    348       && !endsWith(message.component_name(), "Callback")) {
    349     DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations(out, message);
    350   }
    351 }
    352 
    353 void HalHidlCodeGen::GenerateCppBodyGlobalFunctions(Formatter& out,
    354     const ComponentSpecificationMessage& message,
    355     const string& fuzzer_extended_class_name) {
    356   if (message.component_name() != "types"
    357       && !endsWith(message.component_name(), "Callback")) {
    358     DriverCodeGenBase::GenerateCppBodyGlobalFunctions(
    359         out, message, fuzzer_extended_class_name);
    360   }
    361 }
    362 
    363 void HalHidlCodeGen::GenerateClassHeader(Formatter& out,
    364     const ComponentSpecificationMessage& message,
    365     const string& fuzzer_extended_class_name) {
    366   if (message.component_name() != "types"
    367       && !endsWith(message.component_name(), "Callback")) {
    368     for (const auto attribute : message.interface().attribute()) {
    369       GenerateAllFunctionDeclForAttribute(out, attribute);
    370     }
    371     DriverCodeGenBase::GenerateClassHeader(out, message,
    372                                            fuzzer_extended_class_name);
    373   } else if (message.component_name() == "types") {
    374     for (const auto attribute : message.attribute()) {
    375       GenerateAllFunctionDeclForAttribute(out, attribute);
    376     };
    377   } else if (endsWith(message.component_name(), "Callback")) {
    378     for (const auto attribute : message.interface().attribute()) {
    379       GenerateAllFunctionDeclForAttribute(out, attribute);
    380     }
    381 
    382     out << "\n";
    383     FQName component_fq_name = GetFQName(message);
    384     string component_name_token = "Vts_" + component_fq_name.tokenName();;
    385     out << "class " << component_name_token << " : public "
    386         << component_fq_name.cppName() << ", public FuzzerCallbackBase {" << "\n";
    387     out << " public:" << "\n";
    388     out.indent();
    389     out << component_name_token << "(const string& callback_socket_name)\n"
    390         << "    : callback_socket_name_(callback_socket_name) {};" << "\n";
    391     out << "\n";
    392     out << "virtual ~" << component_name_token << "()"
    393         << " = default;" << "\n";
    394     out << "\n";
    395     for (const auto& api : message.interface().api()) {
    396       // Generate return statement.
    397       if (CanElideCallback(api)) {
    398         out << "::android::hardware::Return<"
    399             << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
    400       } else {
    401         out << "::android::hardware::Return<void> ";
    402       }
    403       // Generate function call.
    404       out << api.name() << "(\n";
    405       out.indent();
    406       for (int index = 0; index < api.arg_size(); index++) {
    407         const auto& arg = api.arg(index);
    408         if (!isConstType(arg.type())) {
    409           out << GetCppVariableType(arg, &message);
    410         } else {
    411           out << GetCppVariableType(arg, &message, true);
    412         }
    413         out << " arg" << index;
    414         if (index != (api.arg_size() - 1))
    415           out << ",\n";
    416       }
    417       if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
    418         out << ") override;" << "\n\n";
    419       } else {  // handle the case of callbacks.
    420         out << (api.arg_size() != 0 ? ", " : "");
    421         out << "std::function<void(";
    422         for (int index = 0; index < api.return_type_hidl_size(); index++) {
    423           const auto& return_val = api.return_type_hidl(index);
    424           if (!isConstType(return_val.type())) {
    425             out << GetCppVariableType(return_val, &message);
    426           } else {
    427             out << GetCppVariableType(return_val, &message, true);
    428           }
    429           out << " arg" << index;
    430           if (index != (api.return_type_hidl_size() - 1))
    431             out << ",";
    432         }
    433         out << ")>) override;" << "\n\n";
    434       }
    435       out.unindent();
    436     }
    437     out << "\n";
    438     out.unindent();
    439     out << " private:" << "\n";
    440     out.indent();
    441     out << "const string& callback_socket_name_;" << "\n";
    442     out.unindent();
    443     out << "};" << "\n";
    444     out << "\n";
    445 
    446     out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
    447         << component_name_token << "(const string& callback_socket_name);"
    448         << "\n";
    449     out << "\n";
    450   }
    451 }
    452 
    453 void HalHidlCodeGen::GenerateClassImpl(Formatter& out,
    454     const ComponentSpecificationMessage& message,
    455     const string& fuzzer_extended_class_name) {
    456   if (message.component_name() != "types"
    457       && !endsWith(message.component_name(), "Callback")) {
    458     for (auto attribute : message.interface().attribute()) {
    459       GenerateAllFunctionImplForAttribute(out, attribute);
    460     }
    461     GenerateGetServiceImpl(out, message, fuzzer_extended_class_name);
    462     DriverCodeGenBase::GenerateClassImpl(out, message,
    463                                          fuzzer_extended_class_name);
    464   } else if (message.component_name() == "types") {
    465     for (auto attribute : message.attribute()) {
    466       GenerateAllFunctionImplForAttribute(out, attribute);
    467     }
    468   } else if (endsWith(message.component_name(), "Callback")) {
    469     for (auto attribute : message.interface().attribute()) {
    470       GenerateAllFunctionImplForAttribute(out, attribute);
    471     }
    472     GenerateCppBodyCallbackFunction(out, message, fuzzer_extended_class_name);
    473   }
    474 }
    475 
    476 void HalHidlCodeGen::GenerateHeaderIncludeFiles(Formatter& out,
    477     const ComponentSpecificationMessage& message,
    478     const string& fuzzer_extended_class_name) {
    479   DriverCodeGenBase::GenerateHeaderIncludeFiles(out, message,
    480                                                 fuzzer_extended_class_name);
    481 
    482   string package_path_self = message.package();
    483   ReplaceSubString(package_path_self, ".", "/");
    484   string version_self = GetVersionString(message.component_type_version());
    485 
    486   out << "#include <" << package_path_self << "/"
    487       << version_self << "/"
    488       << message.component_name() << ".h>" << "\n";
    489   out << "#include <hidl/HidlSupport.h>" << "\n";
    490 
    491   for (const auto& import : message.import()) {
    492     FQName import_name = FQName(import);
    493     string package_path = import_name.package();
    494     string package_version = import_name.version();
    495     string component_name = import_name.name();
    496     ReplaceSubString(package_path, ".", "/");
    497 
    498     out << "#include <" << package_path << "/" << package_version << "/"
    499         << component_name << ".h>\n";
    500     if (package_path.find("android/hardware") != std::string::npos) {
    501       if (component_name[0] == 'I') {
    502         component_name = component_name.substr(1);
    503       }
    504       out << "#include <" << package_path << "/" << package_version << "/"
    505           << component_name << ".vts.h>\n";
    506     }
    507   }
    508   out << "\n\n";
    509 }
    510 
    511 void HalHidlCodeGen::GenerateSourceIncludeFiles(Formatter& out,
    512     const ComponentSpecificationMessage& message,
    513     const string& fuzzer_extended_class_name) {
    514   DriverCodeGenBase::GenerateSourceIncludeFiles(out, message,
    515                                                 fuzzer_extended_class_name);
    516   out << "#include <hidl/HidlSupport.h>\n";
    517   string input_vfs_file_path(input_vts_file_path_);
    518   string package_path = message.package();
    519   ReplaceSubString(package_path, ".", "/");
    520   out << "#include <" << package_path << "/"
    521       << GetVersionString(message.component_type_version()) << "/"
    522       << message.component_name() << ".h>" << "\n";
    523   for (const auto& import : message.import()) {
    524     FQName import_name = FQName(import);
    525     string package_name = import_name.package();
    526     string package_version = import_name.version();
    527     string component_name = import_name.name();
    528     string package_path = package_name;
    529     ReplaceSubString(package_path, ".", "/");
    530     if (package_name == message.package()
    531         && package_version
    532             == GetVersionString(message.component_type_version())) {
    533       if (component_name == "types") {
    534         out << "#include \""
    535             << input_vfs_file_path.substr(
    536                 0, input_vfs_file_path.find_last_of("\\/"))
    537             << "/types.vts.h\"\n";
    538       } else {
    539         out << "#include \""
    540             << input_vfs_file_path.substr(
    541                 0, input_vfs_file_path.find_last_of("\\/")) << "/"
    542             << component_name.substr(1) << ".vts.h\"\n";
    543       }
    544     } else {
    545       out << "#include <" << package_path << "/" << package_version << "/"
    546           << component_name << ".h>\n";
    547     }
    548   }
    549 }
    550 
    551 void HalHidlCodeGen::GenerateAdditionalFuctionDeclarations(Formatter& out,
    552     const ComponentSpecificationMessage& message,
    553     const string& /*fuzzer_extended_class_name*/) {
    554   if (message.component_name() != "types"
    555       && !endsWith(message.component_name(), "Callback")) {
    556     out << "bool GetService(bool get_stub, const char* service_name);"
    557         << "\n\n";
    558   }
    559 }
    560 
    561 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
    562     const ComponentSpecificationMessage& message) {
    563   FQName fqname = GetFQName(message);
    564   out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
    565 }
    566 
    567 void HalHidlCodeGen::GenerateRandomFunctionDeclForAttribute(Formatter& out,
    568     const VariableSpecificationMessage& attribute) {
    569   if (attribute.type() == TYPE_ENUM) {
    570     if (attribute.enum_value().enumerator_size() == 0) {
    571       // empty enum without any actual enumerator.
    572       return;
    573     }
    574     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
    575     out << attribute.name() << " " << "Random" << attribute_name << "();\n";
    576   }
    577 }
    578 
    579 void HalHidlCodeGen::GenerateRandomFunctionImplForAttribute(Formatter& out,
    580     const VariableSpecificationMessage& attribute) {
    581   // Random value generator
    582   if (attribute.type() == TYPE_ENUM) {
    583     if (attribute.enum_value().enumerator_size() == 0) {
    584       // empty enum without any actual enumerator.
    585       return;
    586     }
    587     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
    588     out << attribute.name() << " " << "Random" << attribute_name << "() {"
    589         << "\n";
    590     out.indent();
    591     out << attribute.enum_value().scalar_type() << " choice = " << "("
    592         << attribute.enum_value().scalar_type() << ") " << "rand() / "
    593         << attribute.enum_value().enumerator().size() << ";" << "\n";
    594     if (attribute.enum_value().scalar_type().find("u") != 0) {
    595       out << "if (choice < 0) choice *= -1;" << "\n";
    596     }
    597     for (int index = 0; index < attribute.enum_value().enumerator().size();
    598         index++) {
    599       out << "if (choice == ";
    600       out << "(" << attribute.enum_value().scalar_type() << ") ";
    601       if (attribute.enum_value().scalar_type() == "int8_t") {
    602         out << attribute.enum_value().scalar_value(index).int8_t();
    603       } else if (attribute.enum_value().scalar_type() == "uint8_t") {
    604         out << attribute.enum_value().scalar_value(index).uint8_t();
    605       } else if (attribute.enum_value().scalar_type() == "int16_t") {
    606         out << attribute.enum_value().scalar_value(index).int16_t();
    607       } else if (attribute.enum_value().scalar_type() == "uint16_t") {
    608         out << attribute.enum_value().scalar_value(index).uint16_t();
    609       } else if (attribute.enum_value().scalar_type() == "int32_t") {
    610         out << attribute.enum_value().scalar_value(index).int32_t();
    611       } else if (attribute.enum_value().scalar_type() == "uint32_t") {
    612         out << attribute.enum_value().scalar_value(index).uint32_t();
    613       } else if (attribute.enum_value().scalar_type() == "int64_t") {
    614         out << attribute.enum_value().scalar_value(index).int64_t();
    615       } else if (attribute.enum_value().scalar_type() == "uint64_t") {
    616         out << attribute.enum_value().scalar_value(index).uint64_t();
    617       } else {
    618         cerr << __func__ << ":" << __LINE__ << " ERROR unsupported enum type "
    619             << attribute.enum_value().scalar_type() << "\n";
    620         exit(-1);
    621       }
    622       out << ") return " << attribute.name() << "::"
    623           << attribute.enum_value().enumerator(index) << ";" << "\n";
    624     }
    625     out << "return " << attribute.name() << "::"
    626         << attribute.enum_value().enumerator(0) << ";" << "\n";
    627     out.unindent();
    628     out << "}" << "\n";
    629   }
    630 }
    631 
    632 void HalHidlCodeGen::GenerateDriverDeclForAttribute(Formatter& out,
    633     const VariableSpecificationMessage& attribute) {
    634   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
    635     // Recursively generate SetResult method implementation for all sub_types.
    636     for (const auto sub_struct : attribute.sub_struct()) {
    637       GenerateDriverDeclForAttribute(out, sub_struct);
    638     }
    639     for (const auto sub_union : attribute.sub_union()) {
    640       GenerateDriverDeclForAttribute(out, sub_union);
    641     }
    642     string func_name = "MessageTo"
    643         + ClearStringWithNameSpaceAccess(attribute.name());
    644     out << "void " << func_name
    645         << "(const VariableSpecificationMessage& var_msg, " << attribute.name()
    646         << "* arg);\n";
    647   } else if (attribute.type() == TYPE_ENUM) {
    648     string func_name = "EnumValue"
    649             + ClearStringWithNameSpaceAccess(attribute.name());
    650     // Message to value converter
    651     out << attribute.name() << " " << func_name
    652         << "(const ScalarDataValueMessage& arg);\n";
    653   } else {
    654     cerr << __func__ << " unsupported attribute type " << attribute.type()
    655          << "\n";
    656     exit(-1);
    657   }
    658 }
    659 
    660 void HalHidlCodeGen::GenerateDriverImplForAttribute(Formatter& out,
    661     const VariableSpecificationMessage& attribute) {
    662   switch (attribute.type()) {
    663     case TYPE_ENUM:
    664     {
    665       string func_name = "EnumValue"
    666           + ClearStringWithNameSpaceAccess(attribute.name());
    667       // Message to value converter
    668       out << attribute.name() << " " << func_name
    669           << "(const ScalarDataValueMessage& arg) {\n";
    670       out.indent();
    671       out << "return (" << attribute.name() << ") arg."
    672           << attribute.enum_value().scalar_type() << "();\n";
    673       out.unindent();
    674       out << "}" << "\n";
    675       break;
    676     }
    677     case TYPE_STRUCT:
    678     {
    679       // Recursively generate driver implementation method for all sub_types.
    680       for (const auto sub_struct : attribute.sub_struct()) {
    681         GenerateDriverImplForAttribute(out, sub_struct);
    682       }
    683       string func_name = "MessageTo"
    684           + ClearStringWithNameSpaceAccess(attribute.name());
    685       out << "void " << func_name
    686           << "(const VariableSpecificationMessage& var_msg, "
    687           << attribute.name() << "* arg) {" << "\n";
    688       out.indent();
    689       int struct_index = 0;
    690       for (const auto& struct_value : attribute.struct_value()) {
    691         GenerateDriverImplForTypedVariable(
    692             out, struct_value, "arg->" + struct_value.name(),
    693             "var_msg.struct_value(" + std::to_string(struct_index) + ")");
    694         struct_index++;
    695       }
    696       out.unindent();
    697       out << "}\n";
    698       break;
    699     }
    700     case TYPE_UNION:
    701     {
    702       // Recursively generate driver implementation method for all sub_types.
    703       for (const auto sub_union : attribute.sub_union()) {
    704         GenerateDriverImplForAttribute(out, sub_union);
    705       }
    706       string func_name = "MessageTo"
    707           + ClearStringWithNameSpaceAccess(attribute.name());
    708       out << "void " << func_name
    709           << "(const VariableSpecificationMessage& var_msg, "
    710           << attribute.name() << "* arg) {" << "\n";
    711       out.indent();
    712       int union_index = 0;
    713       for (const auto& union_value : attribute.union_value()) {
    714         out << "if (var_msg.union_value(" << union_index << ").name() == \""
    715             << union_value.name() << "\") {" << "\n";
    716         out.indent();
    717         GenerateDriverImplForTypedVariable(
    718             out, union_value, "arg->" + union_value.name(),
    719             "var_msg.union_value(" + std::to_string(union_index) + ")");
    720         union_index++;
    721         out.unindent();
    722         out << "}" << "\n";
    723       }
    724       out.unindent();
    725       out << "}\n";
    726       break;
    727     }
    728     default:
    729     {
    730       cerr << __func__ << " unsupported attribute type " << attribute.type()
    731            << "\n";
    732       exit(-1);
    733     }
    734   }
    735 }
    736 
    737 void HalHidlCodeGen::GenerateGetServiceImpl(Formatter& out,
    738     const ComponentSpecificationMessage& message,
    739     const string& fuzzer_extended_class_name) {
    740   out << "bool " << fuzzer_extended_class_name
    741       << "::GetService(bool get_stub, const char* service_name) {" << "\n";
    742   out.indent();
    743   out << "static bool initialized = false;" << "\n";
    744   out << "if (!initialized) {" << "\n";
    745   out.indent();
    746   out << "cout << \"[agent:hal] HIDL getService\" << endl;" << "\n";
    747   out << "if (service_name) {\n"
    748       << "  cout << \"  - service name: \" << service_name << endl;" << "\n"
    749       << "}\n";
    750   FQName fqname = GetFQName(message);
    751   out << kInstanceVariableName << " = " << fqname.cppName() << "::getService("
    752       << "service_name, get_stub);" << "\n";
    753   out << "cout << \"[agent:hal] " << kInstanceVariableName << " = \" << "
    754       << kInstanceVariableName << ".get() << endl;" << "\n";
    755   out << "initialized = true;" << "\n";
    756   out.unindent();
    757   out << "}" << "\n";
    758   out << "return true;" << "\n";
    759   out.unindent();
    760   out << "}" << "\n" << "\n";
    761 }
    762 
    763 void HalHidlCodeGen::GenerateDriverImplForTypedVariable(Formatter& out,
    764     const VariableSpecificationMessage& val, const string& arg_name,
    765     const string& arg_value_name) {
    766   switch (val.type()) {
    767     case TYPE_SCALAR:
    768     {
    769       out << arg_name << " = " << arg_value_name << ".scalar_value()."
    770           << val.scalar_type() << "();\n";
    771       break;
    772     }
    773     case TYPE_STRING:
    774     {
    775       out << arg_name << " = ::android::hardware::hidl_string("
    776           << arg_value_name << ".string_value().message());\n";
    777       break;
    778     }
    779     case TYPE_ENUM:
    780     {
    781       if (val.has_predefined_type()) {
    782         string func_name = "EnumValue"
    783             + ClearStringWithNameSpaceAccess(val.predefined_type());
    784         out << arg_name << " = " << func_name << "(" << arg_value_name
    785             << ".scalar_value());\n";
    786       } else {
    787         out << arg_name << " = (" << val.name() << ")" << arg_value_name << "."
    788             << "enum_value().scalar_value(0)." << val.enum_value().scalar_type()
    789             << "();\n";
    790       }
    791       break;
    792     }
    793     case TYPE_MASK:
    794     {
    795       out << arg_name << " = " << arg_value_name << ".scalar_value()."
    796           << val.scalar_type() << "();\n";
    797       break;
    798     }
    799     case TYPE_VECTOR:
    800     {
    801       out << arg_name << ".resize(" << arg_value_name
    802           << ".vector_value_size());\n";
    803       out << "for (int i = 0; i <" << arg_value_name
    804           << ".vector_value_size(); i++) {\n";
    805       out.indent();
    806       GenerateDriverImplForTypedVariable(out, val.vector_value(0),
    807                                          arg_name + "[i]",
    808                                          arg_value_name + ".vector_value(i)");
    809       out.unindent();
    810       out << "}\n";
    811       break;
    812     }
    813     case TYPE_ARRAY:
    814     {
    815       out << "for (int i = 0; i < " << arg_value_name
    816           << ".vector_value_size(); i++) {\n";
    817       out.indent();
    818       GenerateDriverImplForTypedVariable(out, val.vector_value(0),
    819                                          arg_name + "[i]",
    820                                          arg_value_name + ".vector_value(i)");
    821       out.unindent();
    822       out << "}\n";
    823       break;
    824     }
    825     case TYPE_STRUCT:
    826     {
    827       if (val.has_predefined_type()) {
    828         string func_name = "MessageTo"
    829             + ClearStringWithNameSpaceAccess(val.predefined_type());
    830         out << func_name << "(" << arg_value_name << ", &("
    831             << arg_name << "));\n";
    832       } else {
    833         int struct_index = 0;
    834         for (const auto struct_field : val.struct_value()) {
    835           string struct_field_name = arg_name + "." + struct_field.name();
    836           string struct_field_value_name = arg_value_name + ".struct_value("
    837               + std::to_string(struct_index) + ")";
    838           GenerateDriverImplForTypedVariable(out, struct_field,
    839                                              struct_field_name,
    840                                              struct_field_value_name);
    841           struct_index++;
    842         }
    843       }
    844       break;
    845     }
    846     case TYPE_UNION:
    847     {
    848       if (val.has_predefined_type()) {
    849         string func_name = "MessageTo"
    850             + ClearStringWithNameSpaceAccess(val.predefined_type());
    851         out << func_name << "(" << arg_value_name << ", &(" << arg_name
    852             << "));\n";
    853       } else {
    854         int union_index = 0;
    855         for (const auto union_field : val.union_value()) {
    856           string union_field_name = arg_name + "." + union_field.name();
    857           string union_field_value_name = arg_value_name + ".union_value("
    858               + std::to_string(union_index) + ")";
    859           GenerateDriverImplForTypedVariable(out, union_field, union_field_name,
    860                                              union_field_value_name);
    861           union_index++;
    862         }
    863       }
    864       break;
    865     }
    866     case TYPE_HIDL_CALLBACK:
    867     {
    868       string type_name = val.predefined_type();
    869       ReplaceSubString(type_name, "::", "_");
    870 
    871       out << arg_name << " = VtsFuzzerCreateVts" << type_name
    872           << "(callback_socket_name);\n";
    873       out << "static_cast<" << "Vts" + type_name << "*>(" << arg_name
    874           << ".get())->Register(" << arg_value_name << ");\n";
    875       break;
    876     }
    877     case TYPE_HANDLE:
    878     {
    879       out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
    880       break;
    881     }
    882     case TYPE_HIDL_INTERFACE:
    883     {
    884       out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
    885       break;
    886     }
    887     case TYPE_HIDL_MEMORY:
    888     {
    889       out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
    890       break;
    891     }
    892     case TYPE_POINTER:
    893     {
    894       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
    895       break;
    896     }
    897     case TYPE_FMQ_SYNC:
    898     {
    899       out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
    900       break;
    901     }
    902     case TYPE_FMQ_UNSYNC:
    903     {
    904       out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
    905       break;
    906     }
    907     case TYPE_REF:
    908     {
    909       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
    910       break;
    911     }
    912     default:
    913     {
    914       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
    915       exit(-1);
    916     }
    917   }
    918 }
    919 
    920 // TODO(zhuoyao): Verify results based on verification rules instead of perform
    921 // an exact match.
    922 void HalHidlCodeGen::GenerateVerificationFunctionImpl(Formatter& out,
    923     const ComponentSpecificationMessage& message,
    924     const string& fuzzer_extended_class_name) {
    925   if (message.component_name() != "types"
    926       && !endsWith(message.component_name(), "Callback")) {
    927     // Generate the main profiler function.
    928     out << "\nbool " << fuzzer_extended_class_name
    929         << "::VerifyResults(const FunctionSpecificationMessage& expected_result, "
    930         << "const FunctionSpecificationMessage& actual_result) {\n";
    931     out.indent();
    932     for (const FunctionSpecificationMessage api : message.interface().api()) {
    933       out << "if (!strcmp(actual_result.name().c_str(), \"" << api.name()
    934           << "\")) {\n";
    935       out.indent();
    936       out << "if (actual_result.return_type_hidl_size() != "
    937           << "expected_result.return_type_hidl_size() "
    938           << ") { return false; }\n";
    939       for (int i = 0; i < api.return_type_hidl_size(); i++) {
    940         std::string expected_result = "expected_result.return_type_hidl("
    941             + std::to_string(i) + ")";
    942         std::string actual_result = "actual_result.return_type_hidl("
    943             + std::to_string(i) + ")";
    944         GenerateVerificationCodeForTypedVariable(out, api.return_type_hidl(i),
    945                                                  expected_result,
    946                                                  actual_result);
    947       }
    948       out << "return true;\n";
    949       out.unindent();
    950       out << "}\n";
    951     }
    952     out << "return false;\n";
    953     out.unindent();
    954     out << "}\n\n";
    955   }
    956 }
    957 
    958 void HalHidlCodeGen::GenerateVerificationCodeForTypedVariable(Formatter& out,
    959     const VariableSpecificationMessage& val, const string& expected_result,
    960     const string& actual_result) {
    961   switch (val.type()) {
    962     case TYPE_SCALAR:
    963     {
    964       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
    965           << "() != " << expected_result << ".scalar_value()."
    966           << val.scalar_type() << "()) { return false; }\n";
    967       break;
    968     }
    969     case TYPE_STRING:
    970     {
    971       out << "if (strcmp(" << actual_result
    972           << ".string_value().message().c_str(), " << expected_result
    973           << ".string_value().message().c_str())!= 0)" << "{ return false; }\n";
    974       break;
    975     }
    976     case TYPE_ENUM:
    977     {
    978       if (val.has_predefined_type()) {
    979         string func_name = "Verify"
    980             + ClearStringWithNameSpaceAccess(val.predefined_type());
    981         out << "if(!" << func_name << "(" << expected_result << ", "
    982             << actual_result << ")) { return false; }\n";
    983       } else {
    984         out << "if (" << actual_result << ".scalar_value()."
    985             << val.enum_value().scalar_type() << "() != " << expected_result
    986             << ".scalar_value()." << val.enum_value().scalar_type()
    987             << "()) { return false; }\n";
    988       }
    989       break;
    990     }
    991     case TYPE_MASK:
    992     {
    993       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
    994           << "() != " << expected_result << ".scalar_value()."
    995           << val.scalar_type() << "()) { return false; }\n";
    996       break;
    997     }
    998     case TYPE_VECTOR:
    999     {
   1000       out << "if (" << actual_result << ".vector_value_size() != "
   1001           << expected_result << ".vector_value_size()) {\n";
   1002       out.indent();
   1003       out << "cerr << \"Verification failed for vector size. expected: \" << "
   1004              << expected_result << ".vector_value_size() << \" actual: \" << "
   1005              << actual_result << ".vector_value_size();\n";
   1006       out << "return false;\n";
   1007       out.unindent();
   1008       out << "}\n";
   1009       out << "for (int i = 0; i <" << expected_result
   1010           << ".vector_value_size(); i++) {\n";
   1011       out.indent();
   1012       GenerateVerificationCodeForTypedVariable(
   1013           out, val.vector_value(0), expected_result + ".vector_value(i)",
   1014           actual_result + ".vector_value(i)");
   1015       out.unindent();
   1016       out << "}\n";
   1017       break;
   1018     }
   1019     case TYPE_ARRAY:
   1020     {
   1021       out << "if (" << actual_result << ".vector_value_size() != "
   1022           << expected_result << ".vector_value_size()) {\n";
   1023       out.indent();
   1024       out << "cerr << \"Verification failed for vector size. expected: \" << "
   1025           << expected_result << ".vector_value_size() << \" actual: \" << "
   1026           << actual_result << ".vector_value_size();\n";
   1027       out << "return false;\n";
   1028       out.unindent();
   1029       out << "}\n";
   1030       out << "for (int i = 0; i < " << expected_result
   1031           << ".vector_value_size(); i++) {\n";
   1032       out.indent();
   1033       GenerateVerificationCodeForTypedVariable(
   1034           out, val.vector_value(0), expected_result + ".vector_value(i)",
   1035           actual_result + ".vector_value(i)");
   1036       out.unindent();
   1037       out << "}\n";
   1038       break;
   1039     }
   1040     case TYPE_STRUCT:
   1041     {
   1042       if (val.has_predefined_type()) {
   1043         string func_name = "Verify"
   1044             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1045         out << "if (!" << func_name << "(" << expected_result << ", "
   1046             << actual_result << ")) { return false; }\n";
   1047       } else {
   1048         for (int i = 0; i < val.struct_value_size(); i++) {
   1049           string struct_field_actual_result = actual_result + ".struct_value("
   1050               + std::to_string(i) + ")";
   1051           string struct_field_expected_result = expected_result
   1052               + ".struct_value(" + std::to_string(i) + ")";
   1053           GenerateVerificationCodeForTypedVariable(out, val.struct_value(i),
   1054                                                    struct_field_expected_result,
   1055                                                    struct_field_actual_result);
   1056         }
   1057       }
   1058       break;
   1059     }
   1060     case TYPE_UNION:
   1061     {
   1062       if (val.has_predefined_type()) {
   1063         string func_name = "Verify"
   1064             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1065         out << "if (!" << func_name << "(" << expected_result << ", "
   1066             << actual_result << ")) {return false; }\n";
   1067       } else {
   1068         for (int i = 0; i < val.union_value_size(); i++) {
   1069           string union_field_actual_result = actual_result + ".union_value("
   1070               + std::to_string(i) + ")";
   1071           string union_field_expected_result = expected_result + ".union_value("
   1072               + std::to_string(i) + ")";
   1073           GenerateVerificationCodeForTypedVariable(out, val.union_value(i),
   1074                                                    union_field_expected_result,
   1075                                                    union_field_actual_result);
   1076         }
   1077       }
   1078       break;
   1079     }
   1080     case TYPE_HIDL_CALLBACK:
   1081     {
   1082       out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
   1083       break;
   1084     }
   1085     case TYPE_HANDLE:
   1086     {
   1087       out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
   1088       break;
   1089     }
   1090     case TYPE_HIDL_INTERFACE:
   1091     {
   1092       out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
   1093       break;
   1094     }
   1095     case TYPE_HIDL_MEMORY:
   1096     {
   1097       out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
   1098       break;
   1099     }
   1100     case TYPE_POINTER:
   1101     {
   1102       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
   1103       break;
   1104     }
   1105     case TYPE_FMQ_SYNC:
   1106     {
   1107       out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
   1108       break;
   1109     }
   1110     case TYPE_FMQ_UNSYNC:
   1111     {
   1112       out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
   1113       break;
   1114     }
   1115     case TYPE_REF:
   1116     {
   1117       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
   1118       break;
   1119     }
   1120     default:
   1121     {
   1122       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
   1123       exit(-1);
   1124     }
   1125   }
   1126 }
   1127 
   1128 void HalHidlCodeGen::GenerateVerificationDeclForAttribute(Formatter& out,
   1129     const VariableSpecificationMessage& attribute) {
   1130   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1131     // Recursively generate verification method implementation for all sub_types.
   1132     for (const auto sub_struct : attribute.sub_struct()) {
   1133       GenerateVerificationDeclForAttribute(out, sub_struct);
   1134     }
   1135     for (const auto sub_union : attribute.sub_union()) {
   1136       GenerateVerificationDeclForAttribute(out, sub_union);
   1137     }
   1138   }
   1139   std::string func_name = "bool Verify"
   1140       + ClearStringWithNameSpaceAccess(attribute.name());
   1141   out << func_name << "(const VariableSpecificationMessage& expected_result, "
   1142       << "const VariableSpecificationMessage& actual_result);\n";
   1143 }
   1144 
   1145 void HalHidlCodeGen::GenerateVerificationImplForAttribute(Formatter& out,
   1146     const VariableSpecificationMessage& attribute) {
   1147   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1148     // Recursively generate verification method implementation for all sub_types.
   1149     for (const auto sub_struct : attribute.sub_struct()) {
   1150       GenerateVerificationImplForAttribute(out, sub_struct);
   1151     }
   1152     for (const auto sub_union : attribute.sub_union()) {
   1153       GenerateVerificationImplForAttribute(out, sub_union);
   1154     }
   1155   }
   1156   std::string func_name = "bool Verify"
   1157       + ClearStringWithNameSpaceAccess(attribute.name());
   1158   out << func_name << "(const VariableSpecificationMessage& expected_result, "
   1159       << "const VariableSpecificationMessage& actual_result){\n";
   1160   out.indent();
   1161   GenerateVerificationCodeForTypedVariable(out, attribute, "expected_result",
   1162                                            "actual_result");
   1163   out << "return true;\n";
   1164   out.unindent();
   1165   out << "}\n\n";
   1166 }
   1167 
   1168 // TODO(zhuoyao): consider to generalize the pattern for
   1169 // Verification/SetResult/DriverImpl.
   1170 void HalHidlCodeGen::GenerateSetResultCodeForTypedVariable(Formatter& out,
   1171     const VariableSpecificationMessage& val, const string& result_msg,
   1172     const string& result_value) {
   1173   switch (val.type()) {
   1174     case TYPE_SCALAR:
   1175     {
   1176       out << result_msg << "->set_type(TYPE_SCALAR);\n";
   1177       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
   1178           << "\");\n";
   1179       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
   1180           << "(" << result_value << ");\n";
   1181       break;
   1182     }
   1183     case TYPE_STRING:
   1184     {
   1185       out << result_msg << "->set_type(TYPE_STRING);\n";
   1186       out << result_msg << "->mutable_string_value()->set_message" << "("
   1187           << result_value << ".c_str());\n";
   1188       out << result_msg << "->mutable_string_value()->set_length" << "("
   1189           << result_value << ".size());\n";
   1190       break;
   1191     }
   1192     case TYPE_ENUM:
   1193     {
   1194       out << result_msg << "->set_type(TYPE_ENUM);\n";
   1195       if (val.has_predefined_type()) {
   1196         string func_name = "SetResult"
   1197             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1198         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1199       } else {
   1200         const string scalar_type = val.enum_value().scalar_type();
   1201         out << result_msg << "->set_scalar_type(\"" << scalar_type << "\");\n";
   1202         out << result_msg << "->mutable_scalar_value()->set_" << scalar_type
   1203             << "(static_cast<" << scalar_type << ">(" << result_value
   1204             << "));\n";
   1205       }
   1206       break;
   1207     }
   1208     case TYPE_MASK:
   1209     {
   1210       out << result_msg << "->set_type(TYPE_MASK);\n";
   1211       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
   1212           << "\");\n";
   1213       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
   1214           << "(" << result_value << ");\n";
   1215       break;
   1216     }
   1217     case TYPE_VECTOR:
   1218     {
   1219       out << result_msg << "->set_type(TYPE_VECTOR);\n";
   1220       out << result_msg << "->set_vector_size(" << result_value
   1221           << ".size());\n";
   1222       out << "for (int i = 0; i < (int)" << result_value << ".size(); i++) {\n";
   1223       out.indent();
   1224       string vector_element_name = result_msg + "_vector_i";
   1225       out << "auto *" << vector_element_name << " = " << result_msg
   1226           << "->add_vector_value();\n";
   1227       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
   1228                                             vector_element_name,
   1229                                             result_value + "[i]");
   1230       out.unindent();
   1231       out << "}\n";
   1232       break;
   1233     }
   1234     case TYPE_ARRAY:
   1235     {
   1236       out << result_msg << "->set_type(TYPE_ARRAY);\n";
   1237       out << result_msg << "->set_vector_size(" << val.vector_value_size()
   1238           << ");\n";
   1239       out << "for (int i = 0; i < " << val.vector_value_size() << "; i++) {\n";
   1240       out.indent();
   1241       string array_element_name = result_msg + "_array_i";
   1242       out << "auto *" << array_element_name << " = " << result_msg
   1243           << "->add_vector_value();\n";
   1244       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
   1245                                             array_element_name,
   1246                                             result_value + "[i]");
   1247       out.unindent();
   1248       out << "}\n";
   1249       break;
   1250     }
   1251     case TYPE_STRUCT:
   1252     {
   1253       out << result_msg << "->set_type(TYPE_STRUCT);\n";
   1254       if (val.has_predefined_type()) {
   1255         string func_name = "SetResult"
   1256             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1257         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1258       } else {
   1259         for (const auto struct_field : val.struct_value()) {
   1260           string struct_field_name = result_msg + "_" + struct_field.name();
   1261           out << "auto *" << struct_field_name << " = " << result_msg
   1262               << "->add_struct_value();\n";
   1263           GenerateSetResultCodeForTypedVariable(
   1264               out, struct_field, struct_field_name,
   1265               result_value + "." + struct_field.name());
   1266           if (struct_field.has_name()) {
   1267             out << struct_field_name << "->set_name(\""
   1268                 << struct_field.name() << "\");\n";
   1269           }
   1270         }
   1271       }
   1272       break;
   1273     }
   1274     case TYPE_UNION:
   1275     {
   1276       out << result_msg << "->set_type(TYPE_UNION);\n";
   1277       if (val.has_predefined_type()) {
   1278         string func_name = "SetResult"
   1279             + ClearStringWithNameSpaceAccess(val.predefined_type());
   1280         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
   1281       } else {
   1282         for (const auto union_field : val.union_value()) {
   1283           string union_field_name = result_msg + "_" + union_field.name();
   1284           out << "auto *" << union_field_name << " = " << result_msg
   1285               << "->add_union_value();\n";
   1286           GenerateSetResultCodeForTypedVariable(
   1287               out, union_field, union_field_name,
   1288               result_value + "." + union_field.name());
   1289         }
   1290       }
   1291       break;
   1292     }
   1293     case TYPE_HIDL_CALLBACK:
   1294     {
   1295       out << result_msg << "->set_type(TYPE_HIDL_CALLBACK);\n";
   1296       out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
   1297       break;
   1298     }
   1299     case TYPE_HANDLE:
   1300     {
   1301       out << result_msg << "->set_type(TYPE_HANDLE);\n";
   1302       out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
   1303       break;
   1304     }
   1305     case TYPE_HIDL_INTERFACE:
   1306     {
   1307       out << result_msg << "->set_type(TYPE_HIDL_INTERFACE);\n";
   1308       out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
   1309       break;
   1310     }
   1311     case TYPE_HIDL_MEMORY:
   1312     {
   1313       out << result_msg << "->set_type(TYPE_HIDL_MEMORY);\n";
   1314       out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
   1315       break;
   1316     }
   1317     case TYPE_POINTER:
   1318     {
   1319       out << result_msg << "->set_type(TYPE_POINTER);\n";
   1320       out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
   1321       break;
   1322     }
   1323     case TYPE_FMQ_SYNC:
   1324     {
   1325       out << result_msg << "->set_type(TYPE_FMQ_SYNC);\n";
   1326       out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
   1327       break;
   1328     }
   1329     case TYPE_FMQ_UNSYNC:
   1330     {
   1331       out << result_msg << "->set_type(TYPE_FMQ_UNSYNC);\n";
   1332       out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
   1333       break;
   1334     }
   1335     case TYPE_REF:
   1336     {
   1337       out << result_msg << "->set_type(TYPE_REF);\n";
   1338       out << "/* ERROR: TYPE_REF is not supported yet. */\n";
   1339       break;
   1340     }
   1341     default:
   1342     {
   1343       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
   1344       exit(-1);
   1345     }
   1346   }
   1347 }
   1348 
   1349 void HalHidlCodeGen::GenerateSetResultDeclForAttribute(Formatter& out,
   1350     const VariableSpecificationMessage& attribute) {
   1351   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1352     // Recursively generate SetResult method implementation for all sub_types.
   1353     for (const auto sub_struct : attribute.sub_struct()) {
   1354       GenerateSetResultDeclForAttribute(out, sub_struct);
   1355     }
   1356     for (const auto sub_union : attribute.sub_union()) {
   1357       GenerateSetResultDeclForAttribute(out, sub_union);
   1358     }
   1359   }
   1360   string func_name = "void SetResult"
   1361       + ClearStringWithNameSpaceAccess(attribute.name());
   1362   out << func_name << "(VariableSpecificationMessage* result_msg, "
   1363       << attribute.name() << " result_value);\n";
   1364 }
   1365 
   1366 void HalHidlCodeGen::GenerateSetResultImplForAttribute(Formatter& out,
   1367     const VariableSpecificationMessage& attribute) {
   1368   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
   1369     // Recursively generate SetResult method implementation for all sub_types.
   1370     for (const auto sub_struct : attribute.sub_struct()) {
   1371       GenerateSetResultImplForAttribute(out, sub_struct);
   1372     }
   1373     for (const auto sub_union : attribute.sub_union()) {
   1374       GenerateSetResultImplForAttribute(out, sub_union);
   1375     }
   1376   }
   1377   string func_name = "void SetResult"
   1378       + ClearStringWithNameSpaceAccess(attribute.name());
   1379   out << func_name << "(VariableSpecificationMessage* result_msg, "
   1380       << attribute.name() << " result_value){\n";
   1381   out.indent();
   1382   GenerateSetResultCodeForTypedVariable(out, attribute, "result_msg",
   1383                                         "result_value");
   1384   out.unindent();
   1385   out << "}\n\n";
   1386 }
   1387 
   1388 void HalHidlCodeGen::GenerateAllFunctionDeclForAttribute(Formatter& out,
   1389     const VariableSpecificationMessage& attribute) {
   1390   GenerateDriverDeclForAttribute(out, attribute);
   1391   GenerateRandomFunctionDeclForAttribute(out, attribute);
   1392   GenerateVerificationDeclForAttribute(out, attribute);
   1393   GenerateSetResultDeclForAttribute(out, attribute);
   1394 }
   1395 
   1396 void HalHidlCodeGen::GenerateAllFunctionImplForAttribute(Formatter& out,
   1397     const VariableSpecificationMessage& attribute) {
   1398   GenerateDriverImplForAttribute(out, attribute);
   1399   GenerateRandomFunctionImplForAttribute(out, attribute);
   1400   GenerateVerificationImplForAttribute(out, attribute);
   1401   GenerateSetResultImplForAttribute(out, attribute);
   1402 }
   1403 
   1404 bool HalHidlCodeGen::CanElideCallback(
   1405     const FunctionSpecificationMessage& func_msg) {
   1406   // Can't elide callback for void or tuple-returning methods
   1407   if (func_msg.return_type_hidl_size() != 1) {
   1408     return false;
   1409   }
   1410   const VariableType& type = func_msg.return_type_hidl(0).type();
   1411   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
   1412     return false;
   1413   }
   1414   return isElidableType(type);
   1415 }
   1416 
   1417 bool HalHidlCodeGen::isElidableType(const VariableType& type) {
   1418   if (type == TYPE_SCALAR || type == TYPE_ENUM || type == TYPE_MASK
   1419       || type == TYPE_POINTER || type == TYPE_HIDL_INTERFACE
   1420       || type == TYPE_VOID) {
   1421     return true;
   1422   }
   1423   return false;
   1424 }
   1425 
   1426 bool HalHidlCodeGen::isConstType(const VariableType& type) {
   1427   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
   1428     return true;
   1429   }
   1430   if (isElidableType(type)) {
   1431     return false;
   1432   }
   1433   return true;
   1434 }
   1435 
   1436 }  // namespace vts
   1437 }  // namespace android
   1438