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/HalCodeGen.h"
18 
19 #include <iostream>
20 #include <string>
21 
22 #include "VtsCompilerUtils.h"
23 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
24 #include "utils/InterfaceSpecUtil.h"
25 #include "utils/StringUtil.h"
26 
27 using namespace std;
28 using namespace android;
29 
30 namespace android {
31 namespace vts {
32 
33 const char* const HalCodeGen::kInstanceVariableName = "device_";
34 
GenerateCppBodyInterfaceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)35 void HalCodeGen::GenerateCppBodyInterfaceImpl(
36     Formatter& out, const ComponentSpecificationMessage& message,
37     const string& fuzzer_extended_class_name) {
38   bool first_callback = true;
39 
40   for (int i = 0; i < message.interface().attribute_size(); i++) {
41     const VariableSpecificationMessage& attribute = message.interface().attribute(i);
42     if (attribute.type() != TYPE_FUNCTION_POINTER || !attribute.is_callback()) {
43       continue;
44     }
45     string name =
46         "vts_callback_" + fuzzer_extended_class_name + "_" + attribute.name();
47     if (first_callback) {
48       out << "static string callback_socket_name_;" << "\n";
49       first_callback = false;
50     }
51     out << "\n";
52     out << "class " << name << " : public DriverCallbackBase {"
53         << "\n";
54     out << " public:" << "\n";
55     out.indent();
56     out << name << "(const string& callback_socket_name) {" << "\n";
57     out.indent();
58     out << "callback_socket_name_ = callback_socket_name;" << "\n";
59     out.unindent();
60     out << "}" << "\n";
61 
62     int primitive_format_index = 0;
63     for (const FunctionPointerSpecificationMessage& func_pt_spec :
64          attribute.function_pointer()) {
65       const string& callback_name = func_pt_spec.function_name();
66       // TODO: callback's return value is assumed to be 'void'.
67       out << "\n";
68       out << "static ";
69       bool has_return_value = false;
70       if (!func_pt_spec.has_return_type() ||
71           !func_pt_spec.return_type().has_type() ||
72           func_pt_spec.return_type().type() == TYPE_VOID) {
73         out << "void" << "\n";
74       } else if (func_pt_spec.return_type().type() == TYPE_PREDEFINED) {
75         out << func_pt_spec.return_type().predefined_type();
76         has_return_value = true;
77       } else {
78         cerr << __func__ << ":" << __LINE__ << " ERROR unknown type "
79              << func_pt_spec.return_type().type() << "\n";
80         exit(-1);
81       }
82       out << " " << callback_name << "(";
83       int primitive_type_index;
84       primitive_type_index = 0;
85       for (const auto& arg : func_pt_spec.arg()) {
86         if (primitive_type_index != 0) {
87           out << ", ";
88         }
89         if (arg.is_const()) {
90           out << "const ";
91         }
92         if (arg.type() == TYPE_SCALAR) {
93           /*
94           if (arg.scalar_type() == "pointer") {
95             out << definition.aggregate_value(
96                 primitive_format_index).primitive_name(primitive_type_index)
97                     << " ";
98           } */
99           if (arg.scalar_type() == "char_pointer") {
100             out << "char* ";
101           } else if (arg.scalar_type() == "uchar_pointer") {
102             out << "unsigned char* ";
103           } else if (arg.scalar_type() == "bool_t") {
104             out << "bool ";
105           } else if (arg.scalar_type() == "int8_t" ||
106                      arg.scalar_type() == "uint8_t" ||
107                      arg.scalar_type() == "int16_t" ||
108                      arg.scalar_type() == "uint16_t" ||
109                      arg.scalar_type() == "int32_t" ||
110                      arg.scalar_type() == "uint32_t" ||
111                      arg.scalar_type() == "size_t" ||
112                      arg.scalar_type() == "int64_t" ||
113                      arg.scalar_type() == "uint64_t") {
114             out << arg.scalar_type() << " ";
115           } else if (arg.scalar_type() == "void_pointer") {
116             out << "void*";
117           } else {
118             cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
119                  << "\n";
120             exit(-1);
121           }
122         } else if (arg.type() == TYPE_PREDEFINED) {
123           out << arg.predefined_type() << " ";
124         } else {
125           cerr << __func__ << " unsupported type" << "\n";
126           exit(-1);
127         }
128         out << "arg" << primitive_type_index;
129         primitive_type_index++;
130       }
131       out << ") {" << "\n";
132       out.indent();
133 #if USE_VAARGS
134       out << "    const char fmt[] = \""
135              << definition.primitive_format(primitive_format_index) << "\";"
136              << "\n";
137       out << "    va_list argp;" << "\n";
138       out << "    const char* p;" << "\n";
139       out << "    int i;" << "\n";
140       out << "    char* s;" << "\n";
141       out << "    char fmtbuf[256];" << "\n";
142       out << "\n";
143       out << "    va_start(argp, fmt);" << "\n";
144       out << "\n";
145       out << "    for (p = fmt; *p != '\\0'; p++) {" << "\n";
146       out << "      if (*p != '%') {" << "\n";
147       out << "        putchar(*p);" << "\n";
148       out << "        continue;" << "\n";
149       out << "      }" << "\n";
150       out << "      switch (*++p) {" << "\n";
151       out << "        case 'c':" << "\n";
152       out << "          i = va_arg(argp, int);" << "\n";
153       out << "          putchar(i);" << "\n";
154       out << "          break;" << "\n";
155       out << "        case 'd':" << "\n";
156       out << "          i = va_arg(argp, int);" << "\n";
157       out << "          s = itoa(i, fmtbuf, 10);" << "\n";
158       out << "          fputs(s, stdout);" << "\n";
159       out << "          break;" << "\n";
160       out << "        case 's':" << "\n";
161       out << "          s = va_arg(argp, char *);" << "\n";
162       out << "          fputs(s, stdout);" << "\n";
163       out << "          break;" << "\n";
164       // out << "        case 'p':
165       out << "        case '%':" << "\n";
166       out << "          putchar('%');" << "\n";
167       out << "          break;" << "\n";
168       out << "      }" << "\n";
169       out << "    }" << "\n";
170       out << "    va_end(argp);" << "\n";
171 #endif
172       // TODO: check whether bytes is set and handle properly if not.
173       out << "AndroidSystemCallbackRequestMessage callback_message;"
174              << "\n";
175       out << "callback_message.set_id(GetCallbackID(\"" << callback_name
176              << "\"));" << "\n";
177 
178       primitive_type_index = 0;
179       for (const auto& arg : func_pt_spec.arg()) {
180         out << "VariableSpecificationMessage* var_msg" << primitive_type_index
181                << " = callback_message.add_arg();" << "\n";
182         if (arg.type() == TYPE_SCALAR) {
183           out << "var_msg" << primitive_type_index << "->set_type("
184                  << "TYPE_SCALAR);" << "\n";
185           out << "var_msg" << primitive_type_index << "->set_scalar_type(\""
186                  << arg.scalar_type() << "\");" << "\n";
187           out << "var_msg" << primitive_type_index << "->mutable_scalar_value()";
188           if (arg.scalar_type() == "bool_t") {
189             out << "->set_" << arg.scalar_type() << "("
190                 << arg.scalar_value().bool_t() << ");" << "\n";
191           } else if (arg.scalar_type() == "int8_t") {
192             out << "->set_" << arg.scalar_type() << "("
193                 << arg.scalar_value().int8_t() << ");" << "\n";
194           } else if (arg.scalar_type() == "uint8_t") {
195             out << "->set_" << arg.scalar_type() << "("
196                 << arg.scalar_value().uint8_t() << ");" << "\n";
197           } else if (arg.scalar_type() == "int16_t") {
198             out << "->set_" << arg.scalar_type() << "("
199                 << arg.scalar_value().int16_t() << ");" << "\n";
200           } else if (arg.scalar_type() == "uint16_t") {
201             out << "->set_" << arg.scalar_type() << "("
202                 << arg.scalar_value().uint16_t() << ");" << "\n";
203           } else if (arg.scalar_type() == "int32_t") {
204             out << "->set_" << arg.scalar_type() << "("
205                 << arg.scalar_value().int32_t() << ");" << "\n";
206           } else if (arg.scalar_type() == "uint32_t") {
207             out << "->set_" << arg.scalar_type() << "("
208                 << arg.scalar_value().uint32_t() << ");" << "\n";
209           } else if (arg.scalar_type() == "size_t") {
210             out << "->set_uint32_t("
211                 << arg.scalar_value().uint32_t() << ");" << "\n";
212           } else if (arg.scalar_type() == "int64_t") {
213             out << "->set_" << arg.scalar_type() << "("
214                 << arg.scalar_value().int64_t() << ");" << "\n";
215           } else if (arg.scalar_type() == "uint64_t") {
216             out << "->set_" << arg.scalar_type() << "("
217                 << arg.scalar_value().uint64_t() << ");" << "\n";
218           } else if (arg.scalar_type() == "char_pointer") {
219             // pointer value is not meaning when it is passed to another machine.
220             out << "->set_" << arg.scalar_type() << "("
221                 << arg.scalar_value().char_pointer() << ");" << "\n";
222           } else if (arg.scalar_type() == "uchar_pointer") {
223             // pointer value is not meaning when it is passed to another machine.
224             out << "->set_" << arg.scalar_type() << "("
225                 << arg.scalar_value().uchar_pointer() << ");" << "\n";
226           } else if (arg.scalar_type() == "void_pointer") {
227             // pointer value is not meaning when it is passed to another machine.
228             out << "->set_" << arg.scalar_type() << "("
229                 << arg.scalar_value().void_pointer() << ");" << "\n";
230           } else {
231             cerr << __func__ << " unsupported scalar type " << arg.scalar_type()
232                  << "\n";
233             exit(-1);
234           }
235         } else if (arg.type() == TYPE_PREDEFINED) {
236           out << "var_msg" << primitive_type_index << "->set_type("
237               << "TYPE_PREDEFINED);" << "\n";
238           // TODO: actually handle such case.
239         } else {
240           cerr << __func__ << " unsupported type" << "\n";
241           exit(-1);
242         }
243         primitive_type_index++;
244       }
245       out << "RpcCallToAgent(callback_message, callback_socket_name_);"
246           << "\n";
247       if (has_return_value) {
248         // TODO: consider actual return type.
249         out << "return NULL;";
250       }
251       out.unindent();
252       out << "}" << "\n";
253       out << "\n";
254 
255       primitive_format_index++;
256     }
257     out << "\n";
258     out.unindent();
259     out << " private:" << "\n";
260     out << "};" << "\n";
261     out << "\n";
262   }
263 }
264 
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)265 void HalCodeGen::GenerateCppBodyFuzzFunction(
266     Formatter& out, const ComponentSpecificationMessage& message,
267     const string& fuzzer_extended_class_name) {
268   for (auto const& sub_struct : message.interface().sub_struct()) {
269     GenerateCppBodyFuzzFunction(out, sub_struct, fuzzer_extended_class_name,
270                                 message.original_data_structure_name(),
271                                 sub_struct.is_pointer() ? "->" : ".");
272   }
273 
274   out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
275   out << "    FunctionSpecificationMessage* func_msg," << "\n";
276   out << "    void** result, const string& callback_socket_name) {" << "\n";
277   out.indent();
278   out << "const char* func_name = func_msg->name().c_str();" << "\n";
279   out << "LOG(INFO) << \" '\" << func_name << \"'\";"
280       << "\n";
281 
282   // to call another function if it's for a sub_struct
283   if (message.interface().sub_struct().size() > 0) {
284     out << "if (func_msg->parent_path().length() > 0) {" << "\n";
285     out.indent();
286     for (auto const& sub_struct : message.interface().sub_struct()) {
287       GenerateSubStructFuzzFunctionCall(out, sub_struct, "");
288     }
289     out.unindent();
290     out << "}" << "\n";
291   }
292 
293   out << message.original_data_structure_name()
294       << "* local_device = ";
295   out << "reinterpret_cast<" << message.original_data_structure_name()
296       << "*>(" << kInstanceVariableName << ");" << "\n";
297 
298   out << "if (local_device == NULL) {" << "\n";
299   out.indent();
300   out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;"
301       << "\n";
302   out << "local_device = reinterpret_cast<"
303       << message.original_data_structure_name() << "*>(hmi_);\n";
304   out.unindent();
305   out << "}" << "\n";
306   out << "if (local_device == NULL) {" << "\n";
307   out.indent();
308   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
309   out << "return false;" << "\n";
310   out.unindent();
311   out << "}" << "\n";
312 
313   for (auto const& api : message.interface().api()) {
314     out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
315     out.indent();
316     out << "LOG(INFO) << \"match\" <<;\n";
317     // args - definition;
318     int arg_count = 0;
319     for (auto const& arg : api.arg()) {
320       if (arg.is_callback()) {  // arg.type() isn't always TYPE_FUNCTION_POINTER
321         string name = "vts_callback_" + fuzzer_extended_class_name + "_" +
322                       arg.predefined_type();  // TODO - check to make sure name
323                                               // is always correct
324         if (name.back() == '*') name.pop_back();
325         out << name << "* arg" << arg_count << "callback = new ";
326         out << name << "(callback_socket_name);" << "\n";
327         out << "arg" << arg_count << "callback->Register(func_msg->arg("
328             << arg_count << "));" << "\n";
329 
330         out << GetCppVariableType(arg) << " ";
331         out << "arg" << arg_count << " = (" << GetCppVariableType(arg)
332             << ") malloc(sizeof(" << GetCppVariableType(arg) << "));"
333             << "\n";
334         // TODO: think about how to free the malloced callback data structure.
335         // find the spec.
336         bool found = false;
337         cout << name << "\n";
338         for (auto const& attribute : message.interface().attribute()) {
339           if (attribute.type() == TYPE_FUNCTION_POINTER &&
340               attribute.is_callback()) {
341             string target_name = "vts_callback_" + fuzzer_extended_class_name +
342                                  "_" + attribute.name();
343             cout << "compare" << "\n";
344             cout << target_name << "\n";
345             if (name == target_name) {
346               if (attribute.function_pointer_size() > 1) {
347                 for (auto const& func_pt : attribute.function_pointer()) {
348                   out << "arg" << arg_count << "->"
349                       << func_pt.function_name() << " = arg" << arg_count
350                       << "callback->" << func_pt.function_name() << ";"
351                       << "\n";
352                 }
353               } else {
354                 out << "arg" << arg_count << " = arg" << arg_count
355                     << "callback->" << attribute.name() << ";" << "\n";
356               }
357               found = true;
358               break;
359             }
360           }
361         }
362         if (!found) {
363           cerr << __func__ << " ERROR callback definition missing for " << name
364                << " of " << api.name() << "\n";
365           exit(-1);
366         }
367       } else {
368         out << GetCppVariableType(arg) << " ";
369         out << "arg" << arg_count << " = ";
370         if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
371             !strncmp(arg.predefined_type().c_str(),
372                      message.original_data_structure_name().c_str(),
373                      message.original_data_structure_name().length())) {
374           out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
375                  << kInstanceVariableName << ")";
376         } else {
377           std::stringstream msg_ss;
378           msg_ss << "func_msg->arg(" << arg_count << ")";
379           string msg = msg_ss.str();
380 
381           if (arg.type() == TYPE_SCALAR) {
382             out << "(" << msg << ".type() == TYPE_SCALAR)? ";
383             if (arg.scalar_type() == "pointer" ||
384                 arg.scalar_type() == "pointer_pointer" ||
385                 arg.scalar_type() == "char_pointer" ||
386                 arg.scalar_type() == "uchar_pointer" ||
387                 arg.scalar_type() == "void_pointer" ||
388                 arg.scalar_type() == "function_pointer") {
389               out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
390             }
391             out << "(" << msg << ".scalar_value()";
392 
393             if (arg.scalar_type() == "bool_t" ||
394                 arg.scalar_type() == "int32_t" ||
395                 arg.scalar_type() == "uint32_t" ||
396                 arg.scalar_type() == "int64_t" ||
397                 arg.scalar_type() == "uint64_t" ||
398                 arg.scalar_type() == "int16_t" ||
399                 arg.scalar_type() == "uint16_t" ||
400                 arg.scalar_type() == "int8_t" ||
401                 arg.scalar_type() == "uint8_t" ||
402                 arg.scalar_type() == "float_t" ||
403                 arg.scalar_type() == "double_t") {
404               out << "." << arg.scalar_type() << "() ";
405             } else if (arg.scalar_type() == "pointer" ||
406                        arg.scalar_type() == "char_pointer" ||
407                        arg.scalar_type() == "uchar_pointer" ||
408                        arg.scalar_type() == "void_pointer") {
409               out << ".pointer() ";
410             } else {
411               cerr << __func__ << " ERROR unsupported scalar type "
412                    << arg.scalar_type() << "\n";
413               exit(-1);
414             }
415             out << ") : ";
416           } else {
417             cerr << __func__ << " unknown type " << msg << "\n";
418           }
419 
420           out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
421                  << ".type() == TYPE_STRUCT || " << msg
422                  << ".type() == TYPE_SCALAR)? ";
423           out << GetCppInstanceType(arg, msg);
424           out << " : " << GetCppInstanceType(arg) << " )";
425           // TODO: use the given message and call a lib function which converts
426           // a message to a C/C++ struct.
427         }
428         out << ";" << "\n";
429       }
430       out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
431           << ";\n";
432       arg_count++;
433     }
434 
435     // actual function call
436     GenerateCodeToStartMeasurement(out);
437     out << "LOG(INFO) << \"hit2.\" << device_;\n";
438 
439     // checks whether the function is actually defined.
440     out << "if (reinterpret_cast<"
441            << message.original_data_structure_name() << "*>(local_device)->"
442            << api.name() << " == NULL" << ") {" << "\n";
443     out.indent();
444     out << "LOG(ERROR) << \"api not set.\";\n";
445     // todo: consider throwing an exception at least a way to tell more
446     // specifically to the caller.
447     out << "return false;" << "\n";
448     out.unindent();
449     out << "}" << "\n";
450 
451     out << "LOG(INFO) << \"Call an API.\";\n";
452     out << "LOG(INFO) << \"local_device = \" << local_device;\n";
453 
454     if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
455       out << "*result = NULL;" << "\n";
456     } else {
457       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
458     }
459     out << "local_device->" << api.name() << "(";
460     if (arg_count > 0) out << "\n";
461 
462     for (int index = 0; index < arg_count; index++) {
463       out << "arg" << index;
464       if (index != (arg_count - 1)) {
465         out << "," << "\n";
466       }
467     }
468 
469     if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
470       out << "))";
471     }
472     out << ");" << "\n";
473     GenerateCodeToStopMeasurement(out);
474     out << "LOG(INFO) << \"called\";\n";
475 
476     // Copy the output (call by pointer or reference cases).
477     arg_count = 0;
478     for (auto const& arg : api.arg()) {
479       if (arg.is_output()) {
480         // TODO check the return value
481         out << GetConversionToProtobufFunctionName(arg) << "(arg"
482             << arg_count << ", "
483             << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
484       }
485       arg_count++;
486     }
487 
488     out << "return true;" << "\n";
489     out.unindent();
490     out << "}" << "\n";
491   }
492   // TODO: if there were pointers, free them.
493   out << "LOG(ERROR) << \"func not found\";\n";
494   out << "return false;" << "\n";
495   out.unindent();
496   out << "}" << "\n";
497 }
498 
GenerateCppBodyFuzzFunction(Formatter & out,const StructSpecificationMessage & message,const string & fuzzer_extended_class_name,const string & original_data_structure_name,const string & parent_path)499 void HalCodeGen::GenerateCppBodyFuzzFunction(
500     Formatter& out, const StructSpecificationMessage& message,
501     const string& fuzzer_extended_class_name,
502     const string& original_data_structure_name, const string& parent_path) {
503   for (auto const& sub_struct : message.sub_struct()) {
504     GenerateCppBodyFuzzFunction(
505         out, sub_struct, fuzzer_extended_class_name,
506         original_data_structure_name,
507         parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
508   }
509 
510   string parent_path_printable(parent_path);
511   ReplaceSubString(parent_path_printable, "->", "_");
512   replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
513 
514   out << "bool " << fuzzer_extended_class_name << "::Fuzz_"
515          << parent_path_printable + message.name() << "(" << "\n";
516   out << "FunctionSpecificationMessage* func_msg," << "\n";
517   out << "void** result, const string& callback_socket_name) {" << "\n";
518   out.indent();
519   out << "const char* func_name = func_msg->name().c_str();" << "\n";
520   out << "LOG(INFO) << func_name;\n";
521 
522   bool is_open;
523   for (auto const& api : message.api()) {
524     is_open = false;
525     if ((parent_path_printable + message.name()) == "_common_methods" &&
526         api.name() == "open") {
527       is_open = true;
528     }
529 
530     out << "if (!strcmp(func_name, \"" << api.name() << "\")) {" << "\n";
531     out.indent();
532 
533     out << original_data_structure_name << "* local_device = ";
534     out << "reinterpret_cast<" << original_data_structure_name << "*>("
535            << kInstanceVariableName << ");" << "\n";
536 
537     out << "if (local_device == NULL) {" << "\n";
538     out.indent();
539     out << "LOG(INFO) << \"use hmi\";\n";
540     out << "local_device = reinterpret_cast<"
541            << original_data_structure_name << "*>(hmi_);" << "\n";
542     out.unindent();
543     out << "}" << "\n";
544     out << "if (local_device == NULL) {" << "\n";
545     out.indent();
546     out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
547     out << "return false;" << "\n";
548     out.unindent();
549     out << "}" << "\n";
550 
551     // args - definition;
552     int arg_count = 0;
553     for (auto const& arg : api.arg()) {
554       out << GetCppVariableType(arg) << " ";
555       out << "arg" << arg_count << " = ";
556       if (arg_count == 0 && arg.type() == TYPE_PREDEFINED &&
557           !strncmp(arg.predefined_type().c_str(),
558                    original_data_structure_name.c_str(),
559                    original_data_structure_name.length())) {
560         out << "reinterpret_cast<" << GetCppVariableType(arg) << ">("
561                << kInstanceVariableName << ")";
562       } else {
563         std::stringstream msg_ss;
564         msg_ss << "func_msg->arg(" << arg_count << ")";
565         string msg = msg_ss.str();
566 
567         if (arg.type() == TYPE_SCALAR) {
568           out << "(" << msg << ".type() == TYPE_SCALAR && " << msg
569                  << ".scalar_value()";
570           if (arg.scalar_type() == "pointer" ||
571               arg.scalar_type() == "char_pointer" ||
572               arg.scalar_type() == "uchar_pointer" ||
573               arg.scalar_type() == "void_pointer" ||
574               arg.scalar_type() == "function_pointer") {
575             out << ".has_pointer())? ";
576             out << "reinterpret_cast<" << GetCppVariableType(arg) << ">";
577           } else {
578             out << ".has_" << arg.scalar_type() << "())? ";
579           }
580           out << "(" << msg << ".scalar_value()";
581 
582           if (arg.scalar_type() == "int32_t" ||
583               arg.scalar_type() == "uint32_t" ||
584               arg.scalar_type() == "int64_t" ||
585               arg.scalar_type() == "uint64_t" ||
586               arg.scalar_type() == "int16_t" ||
587               arg.scalar_type() == "uint16_t" ||
588               arg.scalar_type() == "int8_t" || arg.scalar_type() == "uint8_t" ||
589               arg.scalar_type() == "float_t" ||
590               arg.scalar_type() == "double_t") {
591             out << "." << arg.scalar_type() << "() ";
592           } else if (arg.scalar_type() == "pointer" ||
593                      arg.scalar_type() == "char_pointer" ||
594                      arg.scalar_type() == "uchar_pointer" ||
595                      arg.scalar_type() == "function_pointer" ||
596                      arg.scalar_type() == "void_pointer") {
597             out << ".pointer() ";
598           } else {
599             cerr << __func__ << " ERROR unsupported type " << arg.scalar_type()
600                  << "\n";
601             exit(-1);
602           }
603           out << ") : ";
604         }
605 
606         if (is_open) {
607           if (arg_count == 0) {
608             out << "hmi_;" << "\n";
609           } else if (arg_count == 1) {
610             out << "((hmi_) ? const_cast<char*>(hmi_->name) : NULL)" << "\n";
611           } else if (arg_count == 2) {
612             out << "(struct hw_device_t**) &device_" << "\n";
613           } else {
614             cerr << __func__ << " ERROR additional args for open " << arg_count
615                  << "\n";
616             exit(-1);
617           }
618         } else {
619           out << "( (" << msg << ".type() == TYPE_PREDEFINED || " << msg
620                  << ".type() == TYPE_STRUCT || " << msg
621                  << ".type() == TYPE_SCALAR)? ";
622           out << GetCppInstanceType(arg, msg);
623           out << " : " << GetCppInstanceType(arg) << " )";
624           // TODO: use the given message and call a lib function which converts
625           // a message to a C/C++ struct.
626         }
627       }
628       out << ";" << "\n";
629       out << "LOG(INFO) << \"arg" << arg_count << " = \" << arg" << arg_count
630           << "\n\n";
631       arg_count++;
632     }
633 
634     // actual function call
635     GenerateCodeToStartMeasurement(out);
636     out << "LOG(INFO) << \"hit2.\" << device_;\n";
637 
638     out << "if (reinterpret_cast<" << original_data_structure_name
639            << "*>(local_device)" << parent_path << message.name() << "->"
640            << api.name() << " == NULL";
641     out << ") {" << "\n";
642     out.indent();
643     out << "LOG(ERROR) << \"api not set.\";\n";
644     // todo: consider throwing an exception at least a way to tell more
645     // specifically to the caller.
646     out << "return false;" << "\n";
647     out.unindent();
648     out << "}" << "\n";
649 
650     out << "LOG(INFO) << \"Call an API.\";\n";
651     if (!api.has_return_type() || api.return_type().type() == TYPE_VOID) {
652       out << "*result = NULL;" << "\n";
653     } else {
654       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
655     }
656     out << "local_device" << parent_path << message.name() << "->"
657         << api.name() << "(";
658     if (arg_count > 0) out << "\n";
659 
660     for (int index = 0; index < arg_count; index++) {
661       out << "arg" << index;
662       if (index != (arg_count - 1)) {
663         out << "," << "\n";
664       }
665     }
666     if (api.has_return_type() && api.return_type().type() != TYPE_VOID) {
667       out << "))";
668     }
669     out << ");" << "\n";
670     GenerateCodeToStopMeasurement(out);
671     out << "LOG(INFO) << \"called\";\n";
672 
673     // Copy the output (call by pointer or reference cases).
674     arg_count = 0;
675     for (auto const& arg : api.arg()) {
676       if (arg.is_output()) {
677         // TODO check the return value
678         out << GetConversionToProtobufFunctionName(arg) << "(arg"
679             << arg_count << ", "
680             << "func_msg->mutable_arg(" << arg_count << "));" << "\n";
681       }
682       arg_count++;
683     }
684 
685     out << "return true;" << "\n";
686     out.unindent();
687     out << "}" << "\n";
688   }
689   // TODO: if there were pointers, free them.
690   out << "return false;" << "\n";
691   out.unindent();
692   out << "}" << "\n";
693 }
694 
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)695 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
696     Formatter& out, const ComponentSpecificationMessage& message,
697     const string& fuzzer_extended_class_name) {
698   for (auto const& sub_struct : message.interface().sub_struct()) {
699     GenerateCppBodyGetAttributeFunction(
700         out, sub_struct, fuzzer_extended_class_name,
701         message.original_data_structure_name(),
702         sub_struct.is_pointer() ? "->" : ".");
703   }
704 
705   out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
706   out << "    FunctionSpecificationMessage* func_msg," << "\n";
707   out << "    void** result) {" << "\n";
708   out.indent();
709   out << "const char* func_name = func_msg->name().c_str();" << "\n";
710   out << "LOG(INFO) << \" '\" << func_name << \"'\";\n";
711 
712   // to call another function if it's for a sub_struct
713   if (message.interface().sub_struct().size() > 0) {
714     out << "  if (func_msg->parent_path().length() > 0) {" << "\n";
715     out.indent();
716     for (auto const& sub_struct : message.interface().sub_struct()) {
717       GenerateSubStructGetAttributeFunctionCall(out, sub_struct, "");
718     }
719     out.unindent();
720     out << "}" << "\n";
721   }
722 
723   out << message.original_data_structure_name()
724       << "* local_device = ";
725   out << "reinterpret_cast<" << message.original_data_structure_name()
726       << "*>(" << kInstanceVariableName << ");" << "\n";
727 
728   out << "if (local_device == NULL) {" << "\n";
729   out.indent();
730   out << "LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
731   out << "local_device = reinterpret_cast<"
732          << message.original_data_structure_name() << "*>(hmi_);" << "\n";
733   out.unindent();
734   out << "}" << "\n";
735   out << "if (local_device == NULL) {" << "\n";
736   out.indent();
737   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
738   out << "return false;" << "\n";
739   out.unindent();
740   out << "}" << "\n";
741 
742   for (auto const& attribute : message.interface().attribute()) {
743     if (attribute.type() == TYPE_SUBMODULE ||
744         attribute.type() == TYPE_SCALAR) {
745       out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
746       out.indent();
747       out << "LOG(INFO) << \"match\";\n";
748 
749       // actual function call
750       out << "LOG(INFO) << \"hit2.\" << device_ ;\n";
751 
752       out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
753       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
754       out << "local_device->" << attribute.name();
755       out << "));" << "\n";
756 
757       out << "LOG(INFO) << \"got\";\n";
758 
759       out << "return true;" << "\n";
760       out.unindent();
761       out << "}" << "\n";
762     }
763   }
764   // TODO: if there were pointers, free them.
765   out << "LOG(ERROR) << \"attribute not found\";\n";
766   out << "return false;" << "\n";
767   out.unindent();
768   out << "}" << "\n";
769 }
770 
GenerateCppBodyGetAttributeFunction(Formatter & out,const StructSpecificationMessage & message,const string & fuzzer_extended_class_name,const string & original_data_structure_name,const string & parent_path)771 void HalCodeGen::GenerateCppBodyGetAttributeFunction(
772     Formatter& out, const StructSpecificationMessage& message,
773     const string& fuzzer_extended_class_name,
774     const string& original_data_structure_name, const string& parent_path) {
775   for (auto const& sub_struct : message.sub_struct()) {
776     GenerateCppBodyGetAttributeFunction(
777         out, sub_struct, fuzzer_extended_class_name,
778         original_data_structure_name,
779         parent_path + message.name() + (sub_struct.is_pointer() ? "->" : "."));
780   }
781 
782   string parent_path_printable(parent_path);
783   ReplaceSubString(parent_path_printable, "->", "_");
784   replace(parent_path_printable.begin(), parent_path_printable.end(), '.', '_');
785 
786   out << "bool " << fuzzer_extended_class_name << "::GetAttribute_"
787          << parent_path_printable + message.name() << "(" << "\n";
788   out << "    FunctionSpecificationMessage* func_msg," << "\n";
789   out << "    void** result) {" << "\n";
790   out.indent();
791   out << "const char* func_name = func_msg->name().c_str();" << "\n";
792   out << "LOG(INFO) << func_name;\n";
793 
794   out << original_data_structure_name
795       << "* local_device = ";
796   out << "reinterpret_cast<" << original_data_structure_name
797       << "*>(" << kInstanceVariableName << ");" << "\n";
798 
799   out << "if (local_device == NULL) {" << "\n";
800   out.indent();
801   out << "  LOG(INFO) << \"use hmi \" << (uint64_t)hmi_;\n";
802   out << "  local_device = reinterpret_cast<"
803       << original_data_structure_name << "*>(hmi_);" << "\n";
804   out.unindent();
805   out << "}" << "\n";
806   out << "if (local_device == NULL) {" << "\n";
807   out.indent();
808   out << "LOG(ERROR) << \"both device_ and hmi_ are NULL.\";\n";
809   out << "return false;" << "\n";
810   out.unindent();
811   out << "}" << "\n";
812 
813   for (auto const& attribute : message.attribute()) {
814     if (attribute.type() == TYPE_SUBMODULE ||
815         attribute.type() == TYPE_SCALAR) {
816       out << "if (!strcmp(func_name, \"" << attribute.name() << "\")) {" << "\n";
817       out.indent();
818       out << "LOG(INFO) << \"match\";\n";
819 
820       // actual function call
821       out << "LOG(INFO) << \"hit2.\" << device_;\n";
822 
823       out << "LOG(INFO) << \"ok. let's read attribute.\";\n";
824       out << "*result = const_cast<void*>(reinterpret_cast<const void*>(";
825       out << "local_device" << parent_path << message.name() << ".";
826       // TODO: use parent's is_pointer()
827       out << attribute.name();
828       out << "));" << "\n";
829 
830       out << "LOG(INFO) << \"got\";\n";
831 
832       out << "return true;" << "\n";
833       out.unindent();
834       out << "}" << "\n";
835     }
836   }
837   // TODO: if there were pointers, free them.
838   out << "LOG(ERROR) << \"attribute not found\";\n";
839   out << "return false;" << "\n";
840   out.unindent();
841   out << "}" << "\n";
842 }
843 
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)844 void HalCodeGen::GenerateClassConstructionFunction(Formatter& out,
845       const ComponentSpecificationMessage& /*message*/,
846       const string& fuzzer_extended_class_name) {
847   out << fuzzer_extended_class_name << "() : DriverBase(HAL_CONVENTIONAL) {}\n";
848 }
849 
GenerateSubStructFuzzFunctionCall(Formatter & out,const StructSpecificationMessage & message,const string & parent_path)850 void HalCodeGen::GenerateSubStructFuzzFunctionCall(
851     Formatter& out, const StructSpecificationMessage& message,
852     const string& parent_path) {
853   string current_path(parent_path);
854   if (current_path.length() > 0) {
855     current_path += ".";
856   }
857   current_path += message.name();
858 
859   string current_path_printable(current_path);
860   replace(current_path_printable.begin(), current_path_printable.end(), '.',
861           '_');
862 
863   out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
864       << "\n";
865   out.indent();
866   out << "return Fuzz__" << current_path_printable
867       << "(func_msg, result, callback_socket_name);" << "\n";
868   out.unindent();
869   out << "}" << "\n";
870 
871   for (auto const& sub_struct : message.sub_struct()) {
872     GenerateSubStructFuzzFunctionCall(out, sub_struct, current_path);
873   }
874 }
875 
GenerateSubStructGetAttributeFunctionCall(Formatter & out,const StructSpecificationMessage & message,const string & parent_path)876 void HalCodeGen::GenerateSubStructGetAttributeFunctionCall(
877     Formatter& out, const StructSpecificationMessage& message,
878     const string& parent_path) {
879   string current_path(parent_path);
880   if (current_path.length() > 0) {
881     current_path += ".";
882   }
883   current_path += message.name();
884 
885   string current_path_printable(current_path);
886   replace(current_path_printable.begin(), current_path_printable.end(), '.',
887           '_');
888 
889   out << "if (func_msg->parent_path() == \"" << current_path << "\") {"
890       << "\n";
891   out.indent();
892   out << "      return GetAttribute__" << current_path_printable
893       << "(func_msg, result);" << "\n";
894   out.unindent();
895   out << "}" << "\n";
896 
897   for (auto const& sub_struct : message.sub_struct()) {
898     GenerateSubStructGetAttributeFunctionCall(out, sub_struct, current_path);
899   }
900 }
901 
902 }  // namespace vts
903 }  // namespace android
904