• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GenerateCppBodyCallbackFunction(Formatter & out,const ComponentSpecificationMessage & message,const string &)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 
GenerateScalarTypeInC(Formatter & out,const string & type)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 
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)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 
GenerateDriverFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateDriverImplForReservedMethods(Formatter & out)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 
GenerateDriverImplForMethod(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)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 
GenerateHalFunctionCall(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)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 
GenerateSyncCallbackFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)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 
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateHeaderGlobalFunctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message)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 
GenerateCppBodyGlobalFunctions(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateClassHeader(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateClassImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateHeaderIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateSourceIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateAdditionalFuctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message,const string &)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 
GeneratePrivateMemberDeclarations(Formatter & out,const ComponentSpecificationMessage & message)561 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
562     const ComponentSpecificationMessage& message) {
563   FQName fqname = GetFQName(message);
564   out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
565 }
566 
GenerateRandomFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateRandomFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateDriverDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateDriverImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateGetServiceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateDriverImplForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & arg_name,const string & arg_value_name)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.
GenerateVerificationFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)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 
GenerateVerificationCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & expected_result,const string & actual_result)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 
GenerateVerificationDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateVerificationImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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.
GenerateSetResultCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & result_msg,const string & result_value)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 
GenerateSetResultDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateSetResultImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateAllFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
GenerateAllFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)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 
CanElideCallback(const FunctionSpecificationMessage & func_msg)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 
isElidableType(const VariableType & type)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 
isConstType(const VariableType & type)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