/*
* 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/HalCodeGen.h"
#include <iostream>
#include <string>
#include "VtsCompilerUtils.h"
#include "test/vts/proto/ComponentSpecificationMessage.pb.h"
#include "utils/InterfaceSpecUtil.h"
#include "utils/StringUtil.h"
using namespace std;
using namespace android;
namespace android {
namespace vts {
const char* const HalCodeGen::kInstanceVariableName = "device_";
void HalCodeGen::GenerateCppBodyInterfaceImpl(
Formatter& out, const ComponentSpecificationMessage& message,
const string& fuzzer_extended_class_name) {
bool first_callback = true;
for (int i = 0; i < message.interface().attribute_size(); i++) {
const VariableSpecificationMessage& attribute = message.interface().attribute(i);
if (attribute.type() != TYPE_FUNCTION_POINTER || !attribute.is_callback()) {
continue;
}
string name =
"vts_callback_" + fuzzer_extended_class_name + "_" + attribute.name();
if (first_callback) {
out << "static string callback_socket_name_;" << "\n";
first_callback = false;
}
out << "\n";
out << "class " << name << " : public DriverCallbackBase {"
<< "\n";
out << " public:" << "\n";
out.indent();
out << name << "(const string& callback_socket_name) {" << "\n";
out.indent();
out << "callback_socket_name_ = callback_socket_name;" << "\n";
out.unindent();
out << "}" << "\n";
int primitive_format_index = 0;
for (const FunctionPointerSpecificationMessage& func_pt_spec :
attribute.function_pointer()) {
const string& callback_name = func_pt_spec.function_name();
// TODO: callback's return value is assumed to be 'void'.
out << "\n";
out << "static ";
bool has_return_value = false;
if (!func_pt_spec.has_return_type() ||
!func_pt_spec.return_type().has_type() ||
func_pt_spec.return_type().type() == TYPE_VOID) {
out << "void" << "\n";
} else if (func_pt_spec.return_type().type() == TYPE_PREDEFINED) {
out << func_pt_spec.return_type().predefined_type();
has_return_value = true;
} else {
cerr << __func__ << ":" << __LINE__ << " ERROR unknown type "
<< func_pt_spec.return_type().type() << "\n";
exit(-1);
}
out << " " << callback_name << "(";
int primitive_type_index;
primitive_type_index = 0;
for (const auto& arg : func_pt_spec.arg()) {
if (primitive_type_index != 0) {
out << ", ";
}
if (arg.is_const()) {
out << "const ";
}
if (arg.type() == TYPE_SCALAR) {
/*
if (arg.scalar_type() == "pointer") {
out << definition.aggregate_value(
primitive_format_index).primitive_name(primitive_type_index)
<< " ";
} */
if (arg.scalar_type() == "char_pointer") {
out << "char* ";
} else if (arg.scalar_type() == "uchar_pointer") {
out << "unsigned char* ";
} else if (arg.scalar_type() == "bool_t") {
out << "bool ";
} else if (arg.scalar_type() == "int8_t" ||
arg.scalar_type() == "uint8_t" ||
arg.scalar_type() == "int16_t" ||
arg.scalar_type() == "uint16_t" ||
arg.scalar_type() == "int32_t" ||
arg.scalar_type() == "uint32_t" ||
arg.scalar_type() == "size_t" ||
arg.scalar_type() == "int64_t" ||
arg.scalar_type() == "uint64_t") {
out << arg.scalar_type() << " ";
} else if (arg.scalar_type() == "void_pointer") {
out << "void*";
} else {
cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
<< "\n";
exit(-1);
}
} else if (arg.type() == TYPE_PREDEFINED) {
out << arg.predefined_type() << " ";
} else {
cerr << __func__ << " unsupported type" << "\n";
exit(-1);
}
out << "arg" << primitive_type_index;
primitive_type_index++;
}
out << ") {" << "\n";
out.indent();
#if USE_VAARGS
out << " const char fmt[] = \""
<< definition.primitive_format(primitive_format_index) << "\";"
<< "\n";
out << " va_list argp;" << "\n";
out << " const char* p;" << "\n";
out << " int i;" << "\n";
out << " char* s;" << "\n";
out << " char fmtbuf[256];" << "\n";
out << "\n";
out << " va_start(argp, fmt);" << "\n";
out << "\n";
out << " for (p = fmt; *p != '\\0'; p++) {" << "\n";
out << " if (*p != '%') {" << "\n";
out << " putchar(*p);" << "\n";
out << " continue;" << "\n";
out << " }" << "\n";
out << " switch (*++p) {" << "\n";
out << " case 'c':" << "\n";
out << " i = va_arg(argp, int);" << "\n";
out << " putchar(i);" << "\n";
out << " break;" << "\n";
out << " case 'd':" << "\n";
out << " i = va_arg(argp, int);" << "\n";
out << " s = itoa(i, fmtbuf, 10);" << "\n";
out << " fputs(s, stdout);" << "\n";
out << " break;" << "\n";
out << " case 's':" << "\n";
out << " s = va_arg(argp, char *);" << "\n";
out << " fputs(s, stdout);" << "\n";
out << " break;" << "\n";
// out << " case 'p':
out << " case '%':" << "\n";
out << " putchar('%');" << "\n";
out << " break;" << "\n";
out << " }" << "\n";
out << " }" << "\n";
out << " va_end(argp);" << "\n";
#endif
// TODO: check whether bytes is set and handle properly if not.
out << "AndroidSystemCallbackRequestMessage callback_message;"
<< "\n";
out << "callback_message.set_id(GetCallbackID(\"" << callback_name
<< "\"));" << "\n";
primitive_type_index = 0;
for (const auto& arg : func_pt_spec.arg()) {
out << "VariableSpecificationMessage* var_msg" << primitive_type_index
<< " = callback_message.add_arg();" << "\n";
if (arg.type() == TYPE_SCALAR) {
out << "var_msg" << primitive_type_index << "->set_type("
<< "TYPE_SCALAR);" << "\n";
out << "var_msg" << primitive_type_index << "->set_scalar_type(\""
<< arg.scalar_type() << "\");" << "\n";
out << "var_msg" << primitive_type_index << "->mutable_scalar_value()";
if (arg.scalar_type() == "bool_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().bool_t() << ");" << "\n";
} else if (arg.scalar_type() == "int8_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().int8_t() << ");" << "\n";
} else if (arg.scalar_type() == "uint8_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().uint8_t() << ");" << "\n";
} else if (arg.scalar_type() == "int16_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().int16_t() << ");" << "\n";
} else if (arg.scalar_type() == "uint16_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().uint16_t() << ");" << "\n";
} else if (arg.scalar_type() == "int32_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().int32_t() << ");" << "\n";
} else if (arg.scalar_type() == "uint32_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().uint32_t() << ");" << "\n";
} else if (arg.scalar_type() == "size_t") {
out << "->set_uint32_t("
<< arg.scalar_value().uint32_t() << ");" << "\n";
} else if (arg.scalar_type() == "int64_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().int64_t() << ");" << "\n";
} else if (arg.scalar_type() == "uint64_t") {
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().uint64_t() << ");" << "\n";
} else if (arg.scalar_type() == "char_pointer") {
// pointer value is not meaning when it is passed to another machine.
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().char_pointer() << ");" << "\n";
} else if (arg.scalar_type() == "uchar_pointer") {
// pointer value is not meaning when it is passed to another machine.
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().uchar_pointer() << ");" << "\n";
} else if (arg.scalar_type() == "void_pointer") {
// pointer value is not meaning when it is passed to another machine.
out << "->set_" << arg.scalar_type() << "("
<< arg.scalar_value().void_pointer() << ");" << "\n";
} else {
cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
<< "\n";
exit(-1);
}
} else if (arg.type() == TYPE_PREDEFINED) {
out << "var_msg" << primitive_type_index << "->set_type("
<< "TYPE_PREDEFINED);" << "\n";
// TODO: actually handle such case.
} else {
cerr << __func__ << " unsupported type" << "\n";
exit(-1);
}
primitive_type_index++;
}
out << "RpcCallToAgent(callback_message, callback_socket_name_);"
<< "\n";
if (has_return_value) {
// TODO: consider actual return type.
out << "return NULL;";
}
out.unindent();
out << "}" << "\n";
out << "\n";
primitive_format_index++;
}
out << "\n";
out.unindent();
out << " private:" << "\n";
out << "};" << "\n";
out << "\n";
}
}
void HalCodeGen::GenerateCppBodyFuzzFunction(
Formatter& out, const ComponentSpecificationMessage& message,
const string& fuzzer_extended_class_name) {
for (auto const& sub_struct : message.interface().sub_struct()) {
GenerateCppBodyFuzzFunction(out, sub_struct, fuzzer_extended_class_name,
message.original_data_structure_name(),
sub_struct.is_pointer() ? "->" : ".");
}
out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
out << " FunctionSpecificationMessage* func_msg," << "\n";
out << " void** result, const string& callback_socket_name) {" << "\n";
out.indent();
out << "const char* func_name = func_msg->name().c_str();" << "\n";
out << "LOG(INFO) << \" '\" << func_name << \"'\";"
<< "\n";
// to call another function if it's for a sub_struct
if (message.interface().sub_struct().size() > 0) {
out << "if (func_msg->parent_path().length() > 0) {" << "\n";
out.indent();
for (auto const& sub_struct : message.interface().sub_struct()) {
GenerateSubStructFuzzFunctionCall(out, sub_struct, "");
}
out.unindent();
out << "}" << "\n";
}
out << message.original_data_structure_name()
<< "* local_device = ";
out << "reinterpret_cast<" << message.original_data_structure_name()
<< "*>(" << kInstanceVariableName << ");" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;"
<< "\n";
out << "local_device = reinterpret_cast<"
<< message.original_data_structure_name() << "*>(hmi_);\n";
out.unindent();
out << "}" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
for (auto const& api : message.interface().api()) {
out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
out.indent();
out << "LOG(INFO) << \"match\" <<;\n";
// args - definition;
int arg_count = 0;
for (auto const& arg : api.arg()) {
if (arg.is_callback()) { // arg.type() isn't always TYPE_FUNCTION_POINTER
string name = "vts_callback_" + fuzzer_extended_class_name + "_" +
arg.predefined_type(); // TODO - check to make sure name
// is always correct
if (name.back() == '*') name.pop_back();
out << name << "* arg" << arg_count << "callback = new ";
out << name << "(callback_socket_name);" << "\n";
out << "arg" << arg_count << "callback->Register(func_msg->arg("
<< arg_count << "));" << "\n";
out << GetCppVariableType(arg) << " ";
out << "arg" << arg_count << " = (" << GetCppVariableType(arg)
<< ") malloc(sizeof(" << GetCppVariableType(arg) << "));"
<< "\n";
// TODO: think about how to free the malloced callback data structure.
// find the spec.
bool found = false;
cout << name << "\n";
for (auto const& attribute : message.interface().attribute()) {
if (attribute.type() == TYPE_FUNCTION_POINTER &&
attribute.is_callback()) {
string target_name = "vts_callback_" + fuzzer_extended_class_name +
"_" + attribute.name();
cout << "compare" << "\n";
cout << target_name << "\n";
if (name == target_name) {
if (attribute.function_pointer_size() > 1) {
for (auto const& func_pt : attribute.function_pointer()) {
out << "arg" << arg_count << "->"
<< func_pt.function_name() << " = arg" << arg_count
<< "callback->" << func_pt.function_name() << ";"
<< "\n";
}
} else {
out << "arg" << arg_count << " = arg" << arg_count
<< "callback->" << attribute.name() << ";" << "\n";
}
found = true;
break;
}
}
}
if (!found) {
cerr << __func__ << " ERROR callback definition missing for " << name
<< " of " << api.name() << "\n";
exit(-1);
}
} else {
out << GetCppVariableType(arg) << " ";
out << "arg" << arg_count << " = ";
if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
!strncmp(arg.predefined_type().c_str(),
message.original_data_structure_name().c_str(),
message.original_data_structure_name().length())) {
out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
<< kInstanceVariableName << ")";
} else {
std::stringstream msg_ss;
msg_ss << "func_msg->arg(" << arg_count << ")";
string msg = msg_ss.str();
if (arg.type() == TYPE_SCALAR) {
out << "(" << msg << ".type() == TYPE_SCALAR)? ";
if (arg.scalar_type() == "pointer" ||
arg.scalar_type() == "pointer_pointer" ||
arg.scalar_type() == "char_pointer" ||
arg.scalar_type() == "uchar_pointer" ||
arg.scalar_type() == "void_pointer" ||
arg.scalar_type() == "function_pointer") {
out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
}
out << "(" << msg << ".scalar_value()";
if (arg.scalar_type() == "bool_t" ||
arg.scalar_type() == "int32_t" ||
arg.scalar_type() == "uint32_t" ||
arg.scalar_type() == "int64_t" ||
arg.scalar_type() == "uint64_t" ||
arg.scalar_type() == "int16_t" ||
arg.scalar_type() == "uint16_t" ||
arg.scalar_type() == "int8_t" ||
arg.scalar_type() == "uint8_t" ||
arg.scalar_type() == "float_t" ||
arg.scalar_type() == "double_t") {
out << "." << arg.scalar_type() << "() ";
} else if (arg.scalar_type() == "pointer" ||
arg.scalar_type() == "char_pointer" ||
arg.scalar_type() == "uchar_pointer" ||
arg.scalar_type() == "void_pointer") {
out << ".pointer() ";
} else {
cerr << __func__ << " ERROR unsupported scalar type "
<< arg.scalar_type() << "\n";
exit(-1);
}
out << ") : ";
} else {
cerr << __func__ << " unknown type " << msg << "\n";
}
out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
<< ".type() == TYPE_STRUCT || " << msg
<< ".type() == TYPE_SCALAR)? ";
out << GetCppInstanceType(arg, msg);
out << " : " << GetCppInstanceType(arg) << " )";
// TODO: use the given message and call a lib function which converts
// a message to a C/C++ struct.
}
out << ";" << "\n";
}
out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
<< ";\n";
arg_count++;
}
// actual function call
GenerateCodeToStartMeasurement(out);
out << "LOG(INFO) << \"hit2.\" << device_;\n";
// checks whether the function is actually defined.
out << "if (reinterpret_cast<"
<< message.original_data_structure_name() << "*>(local_device)->"
<< api.name() << " == NULL" << ") {" << "\n";
out.indent();
out << "LOG(ERROR) << \"api not set.\";\n";
// todo: consider throwing an exception at least a way to tell more
// specifically to the caller.
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
out << "LOG(INFO) << \"Call an API.\";\n";
out << "LOG(INFO) << \"local_device = \" << local_device;\n";
if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
out << "*result = NULL;" << "\n";
} else {
out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
}
out << "local_device->" << api.name() << "(";
if (arg_count > 0) out << "\n";
for (int index = 0; index < arg_count; index++) {
out << "arg" << index;
if (index != (arg_count - 1)) {
out << "," << "\n";
}
}
if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
out << "))";
}
out << ");" << "\n";
GenerateCodeToStopMeasurement(out);
out << "LOG(INFO) << \"called\";\n";
// Copy the output (call by pointer or reference cases).
arg_count = 0;
for (auto const& arg : api.arg()) {
if (arg.is_output()) {
// TODO check the return value
out << GetConversionToProtobufFunctionName(arg) << "(arg"
<< arg_count << ", "
<< "func_msg->mutable_arg(" << arg_count << "));" << "\n";
}
arg_count++;
}
out << "return true;" << "\n";
out.unindent();
out << "}" << "\n";
}
// TODO: if there were pointers, free them.
out << "LOG(ERROR) << \"func not found\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
}
void HalCodeGen::GenerateCppBodyFuzzFunction(
Formatter& out, const StructSpecificationMessage& message,
const string& fuzzer_extended_class_name,
const string& original_data_structure_name, const string& parent_path) {
for (auto const& sub_struct : message.sub_struct()) {
GenerateCppBodyFuzzFunction(
out, sub_struct, fuzzer_extended_class_name,
original_data_structure_name,
parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
}
string parent_path_printable(parent_path);
ReplaceSubString(parent_path_printable, "->", "_");
replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
out << "bool " << fuzzer_extended_class_name << "::Fuzz_"
<< parent_path_printable + message.name() << "(" << "\n";
out << "FunctionSpecificationMessage* func_msg," << "\n";
out << "void** result, const string& callback_socket_name) {" << "\n";
out.indent();
out << "const char* func_name = func_msg->name().c_str();" << "\n";
out << "LOG(INFO) << func_name;\n";
bool is_open;
for (auto const& api : message.api()) {
is_open = false;
if ((parent_path_printable + message.name()) == "_common_methods" &&
api.name() == "open") {
is_open = true;
}
out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
out.indent();
out << original_data_structure_name << "* local_device = ";
out << "reinterpret_cast<" << original_data_structure_name << "*>("
<< kInstanceVariableName << ");" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(INFO) << \"use hmi\";\n";
out << "local_device = reinterpret_cast<"
<< original_data_structure_name << "*>(hmi_);" << "\n";
out.unindent();
out << "}" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
// args - definition;
int arg_count = 0;
for (auto const& arg : api.arg()) {
out << GetCppVariableType(arg) << " ";
out << "arg" << arg_count << " = ";
if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
!strncmp(arg.predefined_type().c_str(),
original_data_structure_name.c_str(),
original_data_structure_name.length())) {
out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
<< kInstanceVariableName << ")";
} else {
std::stringstream msg_ss;
msg_ss << "func_msg->arg(" << arg_count << ")";
string msg = msg_ss.str();
if (arg.type() == TYPE_SCALAR) {
out << "(" << msg << ".type() == TYPE_SCALAR && " << msg
<< ".scalar_value()";
if (arg.scalar_type() == "pointer" ||
arg.scalar_type() == "char_pointer" ||
arg.scalar_type() == "uchar_pointer" ||
arg.scalar_type() == "void_pointer" ||
arg.scalar_type() == "function_pointer") {
out << ".has_pointer())? ";
out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
} else {
out << ".has_" << arg.scalar_type() << "())? ";
}
out << "(" << msg << ".scalar_value()";
if (arg.scalar_type() == "int32_t" ||
arg.scalar_type() == "uint32_t" ||
arg.scalar_type() == "int64_t" ||
arg.scalar_type() == "uint64_t" ||
arg.scalar_type() == "int16_t" ||
arg.scalar_type() == "uint16_t" ||
arg.scalar_type() == "int8_t" || arg.scalar_type() == "uint8_t" ||
arg.scalar_type() == "float_t" ||
arg.scalar_type() == "double_t") {
out << "." << arg.scalar_type() << "() ";
} else if (arg.scalar_type() == "pointer" ||
arg.scalar_type() == "char_pointer" ||
arg.scalar_type() == "uchar_pointer" ||
arg.scalar_type() == "function_pointer" ||
arg.scalar_type() == "void_pointer") {
out << ".pointer() ";
} else {
cerr << __func__ << " ERROR unsupported type " << arg.scalar_type()
<< "\n";
exit(-1);
}
out << ") : ";
}
if (is_open) {
if (arg_count == 0) {
out << "hmi_;" << "\n";
} else if (arg_count == 1) {
out << "((hmi_) ? const_cast<char*>(hmi_->name) : NULL)" << "\n";
} else if (arg_count == 2) {
out << "(struct hw_device_t**) &device_" << "\n";
} else {
cerr << __func__ << " ERROR additional args for open " << arg_count
<< "\n";
exit(-1);
}
} else {
out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
<< ".type() == TYPE_STRUCT || " << msg
<< ".type() == TYPE_SCALAR)? ";
out << GetCppInstanceType(arg, msg);
out << " : " << GetCppInstanceType(arg) << " )";
// TODO: use the given message and call a lib function which converts
// a message to a C/C++ struct.
}
}
out << ";" << "\n";
out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
<< "\n\n";
arg_count++;
}
// actual function call
GenerateCodeToStartMeasurement(out);
out << "LOG(INFO) << \"hit2.\" << device_;\n";
out << "if (reinterpret_cast<" << original_data_structure_name
<< "*>(local_device)" << parent_path << message.name() << "->"
<< api.name() << " == NULL";
out << ") {" << "\n";
out.indent();
out << "LOG(ERROR) << \"api not set.\";\n";
// todo: consider throwing an exception at least a way to tell more
// specifically to the caller.
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
out << "LOG(INFO) << \"Call an API.\";\n";
if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
out << "*result = NULL;" << "\n";
} else {
out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
}
out << "local_device" << parent_path << message.name() << "->"
<< api.name() << "(";
if (arg_count > 0) out << "\n";
for (int index = 0; index < arg_count; index++) {
out << "arg" << index;
if (index != (arg_count - 1)) {
out << "," << "\n";
}
}
if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
out << "))";
}
out << ");" << "\n";
GenerateCodeToStopMeasurement(out);
out << "LOG(INFO) << \"called\";\n";
// Copy the output (call by pointer or reference cases).
arg_count = 0;
for (auto const& arg : api.arg()) {
if (arg.is_output()) {
// TODO check the return value
out << GetConversionToProtobufFunctionName(arg) << "(arg"
<< arg_count << ", "
<< "func_msg->mutable_arg(" << arg_count << "));" << "\n";
}
arg_count++;
}
out << "return true;" << "\n";
out.unindent();
out << "}" << "\n";
}
// TODO: if there were pointers, free them.
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
}
void HalCodeGen::GenerateCppBodyGetAttributeFunction(
Formatter& out, const ComponentSpecificationMessage& message,
const string& fuzzer_extended_class_name) {
for (auto const& sub_struct : message.interface().sub_struct()) {
GenerateCppBodyGetAttributeFunction(
out, sub_struct, fuzzer_extended_class_name,
message.original_data_structure_name(),
sub_struct.is_pointer() ? "->" : ".");
}
out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
out << " FunctionSpecificationMessage* func_msg," << "\n";
out << " void** result) {" << "\n";
out.indent();
out << "const char* func_name = func_msg->name().c_str();" << "\n";
out << "LOG(INFO) << \" '\" << func_name << \"'\";\n";
// to call another function if it's for a sub_struct
if (message.interface().sub_struct().size() > 0) {
out << " if (func_msg->parent_path().length() > 0) {" << "\n";
out.indent();
for (auto const& sub_struct : message.interface().sub_struct()) {
GenerateSubStructGetAttributeFunctionCall(out, sub_struct, "");
}
out.unindent();
out << "}" << "\n";
}
out << message.original_data_structure_name()
<< "* local_device = ";
out << "reinterpret_cast<" << message.original_data_structure_name()
<< "*>(" << kInstanceVariableName << ");" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
out << "local_device = reinterpret_cast<"
<< message.original_data_structure_name() << "*>(hmi_);" << "\n";
out.unindent();
out << "}" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
for (auto const& attribute : message.interface().attribute()) {
if (attribute.type() == TYPE_SUBMODULE ||
attribute.type() == TYPE_SCALAR) {
out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
out.indent();
out << "LOG(INFO) << \"match\";\n";
// actual function call
out << "LOG(INFO) << \"hit2.\" << device_ ;\n";
out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
out << "local_device->" << attribute.name();
out << "));" << "\n";
out << "LOG(INFO) << \"got\";\n";
out << "return true;" << "\n";
out.unindent();
out << "}" << "\n";
}
}
// TODO: if there were pointers, free them.
out << "LOG(ERROR) << \"attribute not found\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
}
void HalCodeGen::GenerateCppBodyGetAttributeFunction(
Formatter& out, const StructSpecificationMessage& message,
const string& fuzzer_extended_class_name,
const string& original_data_structure_name, const string& parent_path) {
for (auto const& sub_struct : message.sub_struct()) {
GenerateCppBodyGetAttributeFunction(
out, sub_struct, fuzzer_extended_class_name,
original_data_structure_name,
parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
}
string parent_path_printable(parent_path);
ReplaceSubString(parent_path_printable, "->", "_");
replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
out << "bool " << fuzzer_extended_class_name << "::GetAttribute_"
<< parent_path_printable + message.name() << "(" << "\n";
out << " FunctionSpecificationMessage* func_msg," << "\n";
out << " void** result) {" << "\n";
out.indent();
out << "const char* func_name = func_msg->name().c_str();" << "\n";
out << "LOG(INFO) << func_name;\n";
out << original_data_structure_name
<< "* local_device = ";
out << "reinterpret_cast<" << original_data_structure_name
<< "*>(" << kInstanceVariableName << ");" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << " LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
out << " local_device = reinterpret_cast<"
<< original_data_structure_name << "*>(hmi_);" << "\n";
out.unindent();
out << "}" << "\n";
out << "if (local_device == NULL) {" << "\n";
out.indent();
out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
for (auto const& attribute : message.attribute()) {
if (attribute.type() == TYPE_SUBMODULE ||
attribute.type() == TYPE_SCALAR) {
out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
out.indent();
out << "LOG(INFO) << \"match\";\n";
// actual function call
out << "LOG(INFO) << \"hit2.\" << device_;\n";
out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
out << "local_device" << parent_path << message.name() << ".";
// TODO: use parent's is_pointer()
out << attribute.name();
out << "));" << "\n";
out << "LOG(INFO) << \"got\";\n";
out << "return true;" << "\n";
out.unindent();
out << "}" << "\n";
}
}
// TODO: if there were pointers, free them.
out << "LOG(ERROR) << \"attribute not found\";\n";
out << "return false;" << "\n";
out.unindent();
out << "}" << "\n";
}
void HalCodeGen::GenerateClassConstructionFunction(Formatter& out,
const ComponentSpecificationMessage& /*message*/,
const string& fuzzer_extended_class_name) {
out << fuzzer_extended_class_name << "() : DriverBase(HAL_CONVENTIONAL) {}\n";
}
void HalCodeGen::GenerateSubStructFuzzFunctionCall(
Formatter& out, const StructSpecificationMessage& message,
const string& parent_path) {
string current_path(parent_path);
if (current_path.length() > 0) {
current_path += ".";
}
current_path += message.name();
string current_path_printable(current_path);
replace(current_path_printable.begin(), current_path_printable.end(), '.',
'_');
out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
<< "\n";
out.indent();
out << "return Fuzz__" << current_path_printable
<< "(func_msg, result, callback_socket_name);" << "\n";
out.unindent();
out << "}" << "\n";
for (auto const& sub_struct : message.sub_struct()) {
GenerateSubStructFuzzFunctionCall(out, sub_struct, current_path);
}
}
void HalCodeGen::GenerateSubStructGetAttributeFunctionCall(
Formatter& out, const StructSpecificationMessage& message,
const string& parent_path) {
string current_path(parent_path);
if (current_path.length() > 0) {
current_path += ".";
}
current_path += message.name();
string current_path_printable(current_path);
replace(current_path_printable.begin(), current_path_printable.end(), '.',
'_');
out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
<< "\n";
out.indent();
out << " return GetAttribute__" << current_path_printable
<< "(func_msg, result);" << "\n";
out.unindent();
out << "}" << "\n";
for (auto const& sub_struct : message.sub_struct()) {
GenerateSubStructGetAttributeFunctionCall(out, sub_struct, current_path);
}
}
} // namespace vts
} // namespace android