/* * 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 "ProfilerCodeGenBase.h" #include "utils/InterfaceSpecUtil.h" #include "utils/StringUtil.h" #include "VtsCompilerUtils.h" namespace android { namespace vts { void ProfilerCodeGenBase::GenerateAll( Formatter& header_out, Formatter& source_out, const ComponentSpecificationMessage& message) { GenerateHeaderFile(header_out, message); GenerateSourceFile(source_out, message); } void ProfilerCodeGenBase::GenerateHeaderFile( Formatter& out, const ComponentSpecificationMessage& message) { FQName component_fq_name = GetFQName(message); out << "#ifndef __VTS_PROFILER_" << component_fq_name.tokenName() << "__\n"; out << "#define __VTS_PROFILER_" << component_fq_name.tokenName() << "__\n"; out << "\n\n"; GenerateHeaderIncludeFiles(out, message); GenerateUsingDeclaration(out, message); GenerateOpenNameSpaces(out, message); if (message.has_interface()) { InterfaceSpecificationMessage interface = message.interface(); // First generate the declaration of profiler functions for all user // defined types within the interface. for (const auto& attribute : interface.attribute()) { GenerateProfilerMethodDeclForAttribute(out, attribute); } out << "extern \"C\" {\n"; out.indent(); // Generate the declaration of main profiler function. FQName component_fq_name = GetFQName(message); out << "\nvoid HIDL_INSTRUMENTATION_FUNCTION_" << component_fq_name.tokenName() << "(\n"; out.indent(); out.indent(); out << "details::HidlInstrumentor::InstrumentationEvent event,\n"; out << "const char* package,\n"; out << "const char* version,\n"; out << "const char* interface,\n"; out << "const char* method,\n"; out << "std::vector *args);\n"; out.unindent(); out.unindent(); out.unindent(); out << "}\n\n"; } else { // For types.vts, just generate the declaration of profiler functions // for all user defined types. for (const auto& attribute : message.attribute()) { GenerateProfilerMethodDeclForAttribute(out, attribute); } } GenerateCloseNameSpaces(out, message); out << "#endif\n"; } void ProfilerCodeGenBase::GenerateSourceFile( Formatter& out, const ComponentSpecificationMessage& message) { GenerateSourceIncludeFiles(out, message); GenerateUsingDeclaration(out, message); GenerateMacros(out, message); GenerateOpenNameSpaces(out, message); if (message.has_interface()) { InterfaceSpecificationMessage interface = message.interface(); // First generate profiler functions for all user defined types within // the interface. for (const auto& attribute : interface.attribute()) { GenerateProfilerMethodImplForAttribute(out, attribute); } // Generate the main profiler function. FQName component_fq_name = GetFQName(message); out << "\nvoid HIDL_INSTRUMENTATION_FUNCTION_" << component_fq_name.tokenName() << "(\n"; out.indent(); out.indent(); out << "details::HidlInstrumentor::InstrumentationEvent event " "__attribute__((__unused__)),\n"; out << "const char* package,\n"; out << "const char* version,\n"; out << "const char* interface,\n"; out << "const char* method __attribute__((__unused__)),\n"; out << "std::vector *args __attribute__((__unused__))) {\n"; out.unindent(); // Generate code for profiler check. GenerateProfilerCheck(out, message); if (interface.api_size() > 0) { // Generate code to define local variables. GenerateLocalVariableDefinition(out, message); // Generate the profiler code for each method. for (const FunctionSpecificationMessage& api : interface.api()) { out << "if (strcmp(method, \"" << api.name() << "\") == 0) {\n"; out.indent(); GenerateProfilerForMethod(out, api); out.unindent(); out << "}\n"; } } out.unindent(); out << "}\n\n"; } else { // For types.vts, just generate profiler functions for the user defined // types. for (const auto& attribute : message.attribute()) { GenerateProfilerMethodImplForAttribute(out, attribute); } } GenerateCloseNameSpaces(out, message); } void ProfilerCodeGenBase::GenerateProfilerForTypedVariable(Formatter& out, const VariableSpecificationMessage& val, const std::string& arg_name, const std::string& arg_value) { switch (val.type()) { case TYPE_SCALAR: { GenerateProfilerForScalarVariable(out, val, arg_name, arg_value); break; } case TYPE_STRING: { GenerateProfilerForStringVariable(out, val, arg_name, arg_value); break; } case TYPE_ENUM: { GenerateProfilerForEnumVariable(out, val, arg_name, arg_value); break; } case TYPE_VECTOR: { GenerateProfilerForVectorVariable(out, val, arg_name, arg_value); break; } case TYPE_ARRAY: { GenerateProfilerForArrayVariable(out, val, arg_name, arg_value); break; } case TYPE_STRUCT: { GenerateProfilerForStructVariable(out, val, arg_name, arg_value); break; } case TYPE_UNION: { GenerateProfilerForUnionVariable(out, val, arg_name, arg_value); break; } case TYPE_HIDL_CALLBACK: { GenerateProfilerForHidlCallbackVariable(out, val, arg_name, arg_value); break; } case TYPE_HIDL_INTERFACE: { GenerateProfilerForHidlInterfaceVariable(out, val, arg_name, arg_value); break; } case TYPE_MASK: { GenerateProfilerForMaskVariable(out, val, arg_name, arg_value); break; } case TYPE_HANDLE: { GenerateProfilerForHandleVariable(out, val, arg_name, arg_value); break; } case TYPE_HIDL_MEMORY: { GenerateProfilerForHidlMemoryVariable(out, val, arg_name, arg_value); break; } case TYPE_POINTER: { GenerateProfilerForPointerVariable(out, val, arg_name, arg_value); break; } case TYPE_FMQ_SYNC: { GenerateProfilerForFMQSyncVariable(out, val, arg_name, arg_value); break; } case TYPE_FMQ_UNSYNC: { GenerateProfilerForFMQUnsyncVariable(out, val, arg_name, arg_value); break; } case TYPE_SAFE_UNION: { GenerateProfilerForSafeUnionVariable(out, val, arg_name, arg_value); break; } default: { out << "LOG(ERROR) << \"Type " << val.type() << "is not supported yet. \";\n"; } } } void ProfilerCodeGenBase::GenerateProfilerMethodDeclForAttribute(Formatter& out, const VariableSpecificationMessage& attribute) { if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION || attribute.type() == TYPE_SAFE_UNION) { // Recursively generate profiler method declaration for all sub_types. for (const auto& sub_struct : attribute.sub_struct()) { GenerateProfilerMethodDeclForAttribute(out, sub_struct); } for (const auto& sub_union : attribute.sub_union()) { GenerateProfilerMethodDeclForAttribute(out, sub_union); } for (const auto& sub_safe_union : attribute.sub_safe_union()) { GenerateProfilerMethodDeclForAttribute(out, sub_safe_union); } } std::string attribute_name = attribute.name(); ReplaceSubString(attribute_name, "::", "__"); out << "void profile__" << attribute_name << "(VariableSpecificationMessage* arg_name,\n" << attribute.name() << " arg_val_name);\n"; } void ProfilerCodeGenBase::GenerateProfilerMethodImplForAttribute( Formatter& out, const VariableSpecificationMessage& attribute) { if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION || attribute.type() == TYPE_SAFE_UNION) { // Recursively generate profiler method implementation for all sub_types. for (const auto& sub_struct : attribute.sub_struct()) { GenerateProfilerMethodImplForAttribute(out, sub_struct); } for (const auto& sub_union : attribute.sub_union()) { GenerateProfilerMethodImplForAttribute(out, sub_union); } for (const auto& sub_safe_union : attribute.sub_safe_union()) { GenerateProfilerMethodImplForAttribute(out, sub_safe_union); } } std::string attribute_name = attribute.name(); ReplaceSubString(attribute_name, "::", "__"); out << "void profile__" << attribute_name << "(VariableSpecificationMessage* arg_name,\n" << attribute.name() << " arg_val_name __attribute__((__unused__))) {\n"; out.indent(); GenerateProfilerForTypedVariable(out, attribute, "arg_name", "arg_val_name"); out.unindent(); out << "}\n\n"; } void ProfilerCodeGenBase::GenerateOpenNameSpaces(Formatter& out, const ComponentSpecificationMessage& /*message*/) { out << "namespace android {\n"; out << "namespace vts {\n"; } void ProfilerCodeGenBase::GenerateCloseNameSpaces(Formatter& out, const ComponentSpecificationMessage& /*message*/) { out << "} // namespace vts\n"; out << "} // namespace android\n"; } bool ProfilerCodeGenBase::IncludeHidlNativeType( const ComponentSpecificationMessage& message, const VariableType& type) { if (message.has_interface()) { InterfaceSpecificationMessage interface = message.interface(); for (const VariableSpecificationMessage& attribute : interface.attribute()) { if (IncludeHidlNativeType(attribute, type)) { return true; } } for (const FunctionSpecificationMessage& api : interface.api()) { for (const VariableSpecificationMessage& arg : api.arg()) { if (IncludeHidlNativeType(arg, type)) { return true; } } for (const VariableSpecificationMessage& result : api.return_type_hidl()) { if (IncludeHidlNativeType(result, type)) { return true; } } } } else { for (const VariableSpecificationMessage& attribute : message.attribute()) { if (IncludeHidlNativeType(attribute, type)) { return true; } } } return false; } bool ProfilerCodeGenBase::IncludeHidlNativeType( const VariableSpecificationMessage& val, const VariableType& type) { if (val.type() == type) { return true; } if (val.type() == TYPE_VECTOR || val.type() == TYPE_ARRAY) { if (IncludeHidlNativeType(val.vector_value(0), type)) return true; } if (val.type() == TYPE_STRUCT) { if (!val.has_predefined_type()) { for (const auto& sub_struct : val.sub_struct()) { if (IncludeHidlNativeType(sub_struct, type)) return true; } for (const auto& struct_field : val.struct_value()) { if (IncludeHidlNativeType(struct_field, type)) return true; } } } if (val.type() == TYPE_UNION) { if (!val.has_predefined_type()) { for (const auto& sub_union : val.sub_union()) { if (IncludeHidlNativeType(sub_union, type)) return true; } for (const auto& union_field : val.union_value()) { if (IncludeHidlNativeType(union_field, type)) return true; } } } return false; } } // namespace vts } // namespace android