/* * Copyright 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "code_gen/driver/DriverCodeGenBase.h" #include <iostream> #include <string> #include <hidl-util/Formatter.h> #include <hidl-util/FQName.h> #include "VtsCompilerUtils.h" #include "utils/InterfaceSpecUtil.h" #include "utils/StringUtil.h" using namespace std; namespace android { namespace vts { void DriverCodeGenBase::GenerateAll( Formatter& header_out, Formatter& source_out, const ComponentSpecificationMessage& message) { GenerateHeaderFile(header_out, message); GenerateSourceFile(source_out, message); } void DriverCodeGenBase::GenerateHeaderFile( Formatter& out, const ComponentSpecificationMessage& message) { string component_name = GetComponentName(message); if (component_name.empty()) { cerr << __func__ << ":" << __LINE__ << " error component_name is empty" << "\n"; exit(-1); } string component_name_token; if (message.component_class() == HAL_HIDL) { FQName component_fq_name = GetFQName(message); component_name_token = component_fq_name.tokenName(); } else { string version = GetVersion(message, true); component_name_token = ComponentClassToString(message.component_class()) + "_" + ComponentTypeToString(message.component_type()) + "_" + version; } string fuzzer_extended_class_name; if (message.component_class() == HAL_HIDL) { fuzzer_extended_class_name = "FuzzerExtended_" + component_name_token; } else { fuzzer_extended_class_name = "FuzzerExtended_" + GetComponentName(message); } out << "#ifndef __VTS_DRIVER__" << component_name_token << "__\n"; out << "#define __VTS_DRIVER__" << component_name_token << "__\n"; out << "\n"; out << "#undef LOG_TAG\n"; out << "#define LOG_TAG \"" << fuzzer_extended_class_name << "\"\n"; GenerateHeaderIncludeFiles(out, message, fuzzer_extended_class_name); GenerateOpenNameSpaces(out, message); GenerateClassHeader(out, message, fuzzer_extended_class_name); out << "\n\n"; GenerateHeaderGlobalFunctionDeclarations(out, message); GenerateCloseNameSpaces(out, message); out << "#endif" << "\n"; } void DriverCodeGenBase::GenerateSourceFile( Formatter& out, const ComponentSpecificationMessage& message) { string component_name = GetComponentName(message); if (component_name.empty()) { cerr << __func__ << ":" << __LINE__ << " error component_name is empty" << "\n"; exit(-1); } FQName component_fq_name = GetFQName(message); string component_name_token = component_fq_name.tokenName(); string fuzzer_extended_class_name; if (message.component_class() == HAL_HIDL) { fuzzer_extended_class_name = "FuzzerExtended_" + component_name_token; } else { fuzzer_extended_class_name = "FuzzerExtended_" + GetComponentName(message); } GenerateSourceIncludeFiles(out, message, fuzzer_extended_class_name); out << "\n\n"; GenerateOpenNameSpaces(out, message); GenerateClassImpl(out, message, fuzzer_extended_class_name); GenerateCppBodyGlobalFunctions(out, message, fuzzer_extended_class_name); GenerateCloseNameSpaces(out, message); } void DriverCodeGenBase::GenerateClassHeader(Formatter& out, const ComponentSpecificationMessage& message, const string& fuzzer_extended_class_name) { GenerateHeaderInterfaceImpl(out, message); out << "class " << fuzzer_extended_class_name << " : public DriverBase {" << "\n"; out << " public:" << "\n"; out.indent(); GenerateClassConstructionFunction(out, message, fuzzer_extended_class_name); GeneratePublicFunctionDeclarations(out, message); out.unindent(); out << " protected:" << "\n"; out.indent(); out << "bool Fuzz(FunctionSpecificationMessage* func_msg, void** result, " << "const string& callback_socket_name);\n"; out << "bool CallFunction(const FunctionSpecificationMessage& func_msg, " << "const string& callback_socket_name, " << "FunctionSpecificationMessage* result_msg);\n"; out << "bool VerifyResults(const FunctionSpecificationMessage& expected_result, " << "const FunctionSpecificationMessage& actual_result);\n"; out << "bool GetAttribute(FunctionSpecificationMessage* func_msg, " << "void** result);\n"; // Produce Fuzz method(s) for sub_struct(s). for (auto const& sub_struct : message.interface().sub_struct()) { GenerateFuzzFunctionForSubStruct(out, sub_struct, "_"); } // Generate additional function declarations if any. GenerateAdditionalFuctionDeclarations(out, message, fuzzer_extended_class_name); out.unindent(); out << " private:" << "\n"; out.indent(); // Generate declarations of private members if any. GeneratePrivateMemberDeclarations(out, message); out.unindent(); out << "};\n"; } void DriverCodeGenBase::GenerateClassImpl(Formatter& out, const ComponentSpecificationMessage& message, const string& fuzzer_extended_class_name) { GenerateCppBodyInterfaceImpl(out, message, fuzzer_extended_class_name); GenerateCppBodyFuzzFunction(out, message, fuzzer_extended_class_name); GenerateCppBodyGetAttributeFunction(out, message, fuzzer_extended_class_name); GenerateDriverFunctionImpl(out, message, fuzzer_extended_class_name); GenerateVerificationFunctionImpl(out, message, fuzzer_extended_class_name); } void DriverCodeGenBase::GenerateHeaderIncludeFiles(Formatter& out, const ComponentSpecificationMessage& message, const string&) { for (auto const& header : message.header()) { out << "#include " << header << "\n"; } out << "\n"; out << "#include <stdio.h>" << "\n"; out << "#include <stdarg.h>" << "\n"; out << "#include <stdlib.h>" << "\n"; out << "#include <string.h>" << "\n"; out << "#include <utils/Log.h>" << "\n"; out << "\n"; out << "#include <driver_base/DriverBase.h>" << "\n"; out << "#include <driver_base/DriverCallbackBase.h>" << "\n"; out << "\n"; if (message.component_class() == HAL_HIDL) { out << "#include <VtsDriverCommUtil.h>" << "\n"; out << "\n"; } } void DriverCodeGenBase::GenerateSourceIncludeFiles(Formatter& out, const ComponentSpecificationMessage& message, const string&) { if (message.component_class() != HAL_HIDL) { out << "#include \"" << input_vts_file_path_ << ".h\"\n"; for (auto const& header : message.header()) { out << "#include " << header << "\n"; } out << "#include \"vts_datatype.h\"" << "\n"; } else { out << "#include \"" << GetPackagePath(message) << "/" << GetVersion(message) << "/" << GetComponentBaseName(message) << ".vts.h\"\n"; } out << "#include \"vts_measurement.h\"" << "\n"; out << "#include <android-base/logging.h>" << "\n"; } void DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations( Formatter& out, const ComponentSpecificationMessage& message, const bool print_extern_block) { string function_name_prefix = GetFunctionNamePrefix(message); if (print_extern_block) { out << "extern \"C\" {" << "\n"; } out << "extern " << "android::vts::DriverBase* " << function_name_prefix << "();\n"; if (print_extern_block) { out << "}" << "\n"; } } void DriverCodeGenBase::GenerateCppBodyGlobalFunctions( Formatter& out, const ComponentSpecificationMessage& message, const string& fuzzer_extended_class_name, const bool print_extern_block) { string function_name_prefix = GetFunctionNamePrefix(message); if (print_extern_block) { out << "extern \"C\" {" << "\n"; } out << "android::vts::DriverBase* " << function_name_prefix << "() {\n"; out.indent(); out << "return (android::vts::DriverBase*) " << "new android::vts::"; out << fuzzer_extended_class_name << "();\n"; out.unindent(); out << "}\n\n"; if (print_extern_block) { out << "}\n"; } } void DriverCodeGenBase::GenerateFuzzFunctionForSubStruct( Formatter& out, const StructSpecificationMessage& message, const string& parent_path) { out << "bool Fuzz_" << parent_path << message.name() << "(FunctionSpecificationMessage* func_msg," << "\n"; out << " void** result, const string& callback_socket_name);" << "\n"; out << "bool GetAttribute_" << parent_path << message.name() << "(FunctionSpecificationMessage* /*func_msg*/," << "\n"; out << " void** /*result*/);" << "\n"; for (auto const& sub_struct : message.sub_struct()) { GenerateFuzzFunctionForSubStruct(out, sub_struct, parent_path + message.name() + "_"); } } void DriverCodeGenBase::GenerateDriverFunctionImpl(Formatter& out, const ComponentSpecificationMessage& /*message*/, const string& fuzzer_extended_class_name) { out << "bool " << fuzzer_extended_class_name << "::CallFunction(const FunctionSpecificationMessage&, const string&, " << "FunctionSpecificationMessage* ) {\n"; out.indent(); out << "/* No implementation yet. */\n"; out << "return true;\n"; out.unindent(); out << "}\n"; } void DriverCodeGenBase::GenerateVerificationFunctionImpl(Formatter& out, const ComponentSpecificationMessage& /*message*/, const string& fuzzer_extended_class_name) { out << "bool " << fuzzer_extended_class_name << "::VerifyResults(const FunctionSpecificationMessage&, " << "const FunctionSpecificationMessage&) {\n"; out.indent(); out << "/* No implementation yet. */\n"; out << "return true;\n"; out.unindent(); out << "}\n"; } void DriverCodeGenBase::GenerateNamespaceName( Formatter& out, const ComponentSpecificationMessage& message) { if (message.component_class() == HAL_HIDL && message.has_package()) { out << GetPackageNamespaceToken(message) << "::" << GetVersion(message, true); } else { cerr << __func__ << ":" << __LINE__ << " no namespace" << "\n"; exit(-1); } } void DriverCodeGenBase::GenerateOpenNameSpaces(Formatter& out, const ComponentSpecificationMessage& message) { if (message.component_class() == HAL_HIDL && message.has_package()) { out << "using namespace "; GenerateNamespaceName(out, message); out << ";" << "\n"; } out << "namespace android {" << "\n"; out << "namespace vts {" << "\n"; } void DriverCodeGenBase::GenerateCloseNameSpaces(Formatter& out, const ComponentSpecificationMessage& /*message*/) { out << "} // namespace vts" << "\n"; out << "} // namespace android" << "\n"; } void DriverCodeGenBase::GenerateCodeToStartMeasurement(Formatter& out) { out << "VtsMeasurement vts_measurement;" << "\n"; out << "vts_measurement.Start();" << "\n"; } void DriverCodeGenBase::GenerateCodeToStopMeasurement(Formatter& out) { out << "vector<float>* measured = vts_measurement.Stop();" << "\n"; out << "LOG(INFO) << \"time \" << (*measured)[0];" << "\n"; } } // namespace vts } // namespace android