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 <iostream>
20 #include <string>
21 
22 #include "VtsCompilerUtils.h"
23 #include "code_gen/common/HalHidlCodeGenUtils.h"
24 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
25 #include "utils/InterfaceSpecUtil.h"
26 #include "utils/StringUtil.h"
27 
28 using namespace std;
29 using namespace android;
30 
31 namespace android {
32 namespace vts {
33 
34 const char* const HalHidlCodeGen::kInstanceVariableName = "hw_binder_proxy_";
35 
GenerateCppBodyInterfaceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string &)36 void HalHidlCodeGen::GenerateCppBodyInterfaceImpl(
37     Formatter& out, const ComponentSpecificationMessage& message,
38     const string& /*fuzzer_extended_class_name*/) {
39   out << "\n";
40   FQName component_fq_name = GetFQName(message);
41   for (const auto& api : message.interface().api()) {
42     // Generate return statement.
43     if (CanElideCallback(api)) {
44       out << "::android::hardware::Return<"
45           << GetCppVariableType(api.return_type_hidl(0)) << "> ";
46     } else {
47       out << "::android::hardware::Return<void> ";
48     }
49     // Generate function call.
50     string full_method_name =
51         "Vts_" + component_fq_name.tokenName() + "::" + api.name();
52     out << full_method_name << "(\n";
53     out.indent();
54     for (int index = 0; index < api.arg_size(); index++) {
55       const auto& arg = api.arg(index);
56       out << GetCppVariableType(arg, IsConstType(arg.type())) << " arg" << index
57           << " __attribute__((__unused__))";
58       if (index != (api.arg_size() - 1)) out << ",\n";
59     }
60     if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
61       out << ") {\n";
62     } else {  // handle the case of callbacks.
63       out << (api.arg_size() != 0 ? ", " : "");
64       out << "std::function<void(";
65       for (int index = 0; index < api.return_type_hidl_size(); index++) {
66         const auto& return_val = api.return_type_hidl(index);
67         out << GetCppVariableType(return_val, IsConstType(return_val.type()))
68             << " arg" << index;
69         if (index != (api.return_type_hidl_size() - 1)) {
70           out << ",";
71         }
72       }
73       out << ")> cb) {\n";
74     }
75     out << "LOG(INFO) << \"" << api.name() << " called\";\n";
76     out << "AndroidSystemCallbackRequestMessage callback_message;\n";
77     out << "callback_message.set_id(GetCallbackID(\"" << api.name()
78         << "\"));\n";
79     out << "callback_message.set_name(\"" << full_method_name << "\");\n";
80     for (int index = 0; index < api.arg_size(); index++) {
81       out << "VariableSpecificationMessage* var_msg" << index << " = "
82           << "callback_message.add_arg();\n";
83       GenerateSetResultCodeForTypedVariable(out, api.arg(index),
84                                             "var_msg" + std::to_string(index),
85                                             "arg" + std::to_string(index));
86     }
87     out << "RpcCallToAgent(callback_message, callback_socket_name_);\n";
88 
89     // TODO(zhuoyao): return the received results from host.
90     if (CanElideCallback(api)) {
91       out << "return ";
92       GenerateDefaultReturnValForTypedVariable(out, api.return_type_hidl(0));
93       out << ";\n";
94     } else {
95       if (api.return_type_hidl_size() > 0) {
96         out << "cb(";
97         for (int index = 0; index < api.return_type_hidl_size(); index++) {
98           GenerateDefaultReturnValForTypedVariable(out,
99                                                    api.return_type_hidl(index));
100           if (index != (api.return_type_hidl_size() - 1)) {
101             out << ", ";
102           }
103         }
104         out << ");\n";
105       }
106       out << "return ::android::hardware::Void();\n";
107     }
108     out.unindent();
109     out << "}"
110         << "\n";
111     out << "\n";
112   }
113 
114   string component_name_token = "Vts_" + component_fq_name.tokenName();
115   out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
116       << component_name_token << "(const string& callback_socket_name) {\n";
117   out.indent();
118   out << "static sp<" << component_fq_name.cppName() << "> result;\n";
119   out << "result = new " << component_name_token << "(callback_socket_name);\n";
120   out << "return result;\n";
121   out.unindent();
122   out << "}\n\n";
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 
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)153 void HalHidlCodeGen::GenerateCppBodyFuzzFunction(
154     Formatter& out, const ComponentSpecificationMessage& /*message*/,
155     const string& fuzzer_extended_class_name) {
156     out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
157     out.indent();
158     out << "FunctionSpecificationMessage* /*func_msg*/,"
159         << "\n";
160     out << "void** /*result*/, const string& /*callback_socket_name*/) {\n";
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     out << "bool " << fuzzer_extended_class_name << "::CallFunction("
171         << "\n";
172     out.indent();
173     out << "const FunctionSpecificationMessage& func_msg,"
174         << "\n";
175     out << "const string& callback_socket_name __attribute__((__unused__)),"
176         << "\n";
177     out << "FunctionSpecificationMessage* result_msg) {\n";
178 
179     out << "const char* func_name = func_msg.name().c_str();" << "\n";
180     out << "if (hw_binder_proxy_ == nullptr) {\n";
181     out.indent();
182     out << "LOG(ERROR) << \"" << kInstanceVariableName << " is null. \";\n";
183     out << "return false;\n";
184     out.unindent();
185     out << "}\n";
186     for (auto const& api : message.interface().api()) {
187       GenerateDriverImplForMethod(out, api);
188     }
189 
190     GenerateDriverImplForReservedMethods(out);
191 
192     out << "return false;\n";
193     out.unindent();
194     out << "}\n";
195   }
196 }
197 
GenerateDriverImplForReservedMethods(Formatter & out)198 void HalHidlCodeGen::GenerateDriverImplForReservedMethods(Formatter& out) {
199   // Generate call for reserved method: notifySyspropsChanged.
200   out << "if (!strcmp(func_name, \"notifySyspropsChanged\")) {\n";
201   out.indent();
202 
203   out << "LOG(INFO) << \"Call notifySyspropsChanged\";"
204       << "\n";
205   out << kInstanceVariableName << "->notifySyspropsChanged();\n";
206   out << "result_msg->set_name(\"notifySyspropsChanged\");\n";
207   out << "return true;\n";
208 
209   out.unindent();
210   out << "}\n";
211   // TODO(zhuoyao): Add generation code for other reserved method,
212   // e.g interfaceChain
213 }
214 
GenerateDriverImplForMethod(Formatter & out,const FunctionSpecificationMessage & func_msg)215 void HalHidlCodeGen::GenerateDriverImplForMethod(Formatter& out,
216     const FunctionSpecificationMessage& func_msg) {
217   out << "if (!strcmp(func_name, \"" << func_msg.name() << "\")) {\n";
218   out.indent();
219   // Process the arguments.
220   for (int i = 0; i < func_msg.arg_size(); i++) {
221     const auto& arg = func_msg.arg(i);
222     string cur_arg_name = "arg" + std::to_string(i);
223     string var_type = GetCppVariableType(arg);
224 
225     if (arg.type() == TYPE_POINTER ||
226         (arg.type() == TYPE_SCALAR &&
227          (arg.scalar_type() == "pointer" ||
228           arg.scalar_type() == "void_pointer" ||
229           arg.scalar_type() == "function_pointer"))) {
230       out << var_type << " " << cur_arg_name << " = nullptr;\n";
231     } else if (arg.type() == TYPE_SCALAR) {
232       out << var_type << " " << cur_arg_name << " = 0;\n";
233     } else if (arg.type() == TYPE_FMQ_SYNC || arg.type() == TYPE_FMQ_UNSYNC) {
234       // FMQ type, use pointer to store arguments because copy assignment
235       // is not allowed for fmq descriptor.
236       // Use const because getDesc() function in FMQ implementation
237       // returns const type.
238       out << "const " << var_type << "* " << cur_arg_name << ";\n";
239     } else {
240       out << var_type << " " << cur_arg_name << ";\n";
241     }
242 
243     GenerateDriverImplForTypedVariable(
244         out, arg, cur_arg_name, "func_msg.arg(" + std::to_string(i) + ")");
245   }
246 
247   // may need to check whether the function is actually defined.
248   out << "LOG(DEBUG) << \"local_device = \" << " << kInstanceVariableName
249       << ".get();\n";
250 
251   // Call the HAL function.
252   if (CanElideCallback(func_msg)) {
253     out << GetCppVariableType(func_msg.return_type_hidl(0)) << " result0 = ";
254     GenerateHalFunctionCall(out, func_msg);
255     // Set the return results value to the proto message.
256     for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
257       out << "VariableSpecificationMessage* result_val_" << index << " = "
258           << "result_msg->add_return_type_hidl();\n";
259       GenerateSetResultCodeForTypedVariable(
260           out, func_msg.return_type_hidl(index),
261           "result_val_" + std::to_string(index),
262           "result" + std::to_string(index));
263     }
264   } else {
265     GenerateHalFunctionCall(out, func_msg);
266   }
267 
268   out << "return true;\n";
269   out.unindent();
270   out << "}\n";
271 }
272 
GenerateHalFunctionCall(Formatter & out,const FunctionSpecificationMessage & func_msg)273 void HalHidlCodeGen::GenerateHalFunctionCall(Formatter& out,
274     const FunctionSpecificationMessage& func_msg) {
275   out << kInstanceVariableName << "->" << func_msg.name() << "(";
276   for (int index = 0; index < func_msg.arg_size(); index++) {
277     if (func_msg.arg(index).type() == TYPE_FMQ_SYNC ||
278         func_msg.arg(index).type() == TYPE_FMQ_UNSYNC) {
279       // only FMQ types store arguments as pointers, dereference it now.
280       out << "*arg" << index;
281     } else {
282       out << "arg" << index;
283     }
284     if (index != (func_msg.arg_size() - 1)) out << ", ";
285   }
286   if (func_msg.return_type_hidl_size()== 0 || CanElideCallback(func_msg)) {
287     out << ");\n";
288     out << "result_msg->set_name(\"" << func_msg.name() << "\");\n";
289   } else {
290     out << (func_msg.arg_size() != 0 ? ", " : "");
291     GenerateSyncCallbackFunctionImpl(out, func_msg);
292     out << ");\n";
293   }
294 }
295 
GenerateSyncCallbackFunctionImpl(Formatter & out,const FunctionSpecificationMessage & func_msg)296 void HalHidlCodeGen::GenerateSyncCallbackFunctionImpl(Formatter& out,
297     const FunctionSpecificationMessage& func_msg) {
298   out << "[&](";
299   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
300     const auto& return_val = func_msg.return_type_hidl(index);
301     out << GetCppVariableType(return_val, IsConstType(return_val.type()))
302         << " arg" << index << " __attribute__((__unused__))";
303     if (index != (func_msg.return_type_hidl_size() - 1)) out << ",";
304   }
305   out << "){\n";
306   out.indent();
307   out << "LOG(INFO) << \"callback " << func_msg.name() << " called\""
308       << ";\n";
309 
310   // Set the return results value to the proto message.
311   out << "result_msg->set_name(\"" << func_msg.name() << "\");\n";
312   for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
313     out << "VariableSpecificationMessage* result_val_" << index << " = "
314         << "result_msg->add_return_type_hidl();\n";
315     GenerateSetResultCodeForTypedVariable(out, func_msg.return_type_hidl(index),
316                                           "result_val_" + std::to_string(index),
317                                           "arg" + std::to_string(index));
318   }
319   out.unindent();
320   out << "}";
321 }
322 
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)323 void HalHidlCodeGen::GenerateCppBodyGetAttributeFunction(
324     Formatter& out, const ComponentSpecificationMessage& message,
325     const string& fuzzer_extended_class_name) {
326   if (message.component_name() != "types") {
327     out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
328     out.indent();
329     out << "FunctionSpecificationMessage* /*func_msg*/,"
330         << "\n";
331     out << "void** /*result*/) {"
332         << "\n";
333     // TOOD: impl
334     out << "LOG(ERROR) << \"attribute not found.\";\n"
335         << "return false;\n";
336     out.unindent();
337     out << "}" << "\n";
338   }
339 }
340 
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)341 void HalHidlCodeGen::GenerateClassConstructionFunction(Formatter& out,
342     const ComponentSpecificationMessage& message,
343     const string& fuzzer_extended_class_name) {
344   out << fuzzer_extended_class_name << "() : DriverBase(";
345   if (message.component_name() != "types") {
346     out << "HAL_HIDL), " << kInstanceVariableName << "()";
347   } else {
348     out << "HAL_HIDL)";
349   }
350   out << " {}" << "\n";
351   out << "\n";
352 
353   FQName fqname = GetFQName(message);
354   out << "explicit " << fuzzer_extended_class_name << "(" << fqname.cppName()
355       << "* hw_binder_proxy) : DriverBase("
356       << "HAL_HIDL)";
357   if (message.component_name() != "types") {
358     out << ", " << kInstanceVariableName << "(hw_binder_proxy)";
359   }
360   out << " {}\n";
361 }
362 
GenerateHeaderGlobalFunctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message,const bool print_extern_block)363 void HalHidlCodeGen::GenerateHeaderGlobalFunctionDeclarations(Formatter& out,
364     const ComponentSpecificationMessage& message,
365     const bool print_extern_block) {
366   if (message.component_name() != "types") {
367     if (print_extern_block) {
368       out << "extern \"C\" {" << "\n";
369     }
370     DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations(
371         out, message, false);
372 
373     string function_name_prefix = GetFunctionNamePrefix(message);
374     FQName fqname = GetFQName(message);
375     out << "extern "
376         << "android::vts::DriverBase* " << function_name_prefix
377         << "with_arg(uint64_t hw_binder_proxy);\n";
378     if (print_extern_block) {
379       out << "}" << "\n";
380     }
381   }
382 }
383 
GenerateCppBodyGlobalFunctions(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name,const bool print_extern_block)384 void HalHidlCodeGen::GenerateCppBodyGlobalFunctions(Formatter& out,
385     const ComponentSpecificationMessage& message,
386     const string& fuzzer_extended_class_name, const bool print_extern_block) {
387   if (message.component_name() != "types") {
388     if (print_extern_block) {
389       out << "extern \"C\" {" << "\n";
390     }
391     DriverCodeGenBase::GenerateCppBodyGlobalFunctions(
392         out, message, fuzzer_extended_class_name, false);
393 
394     string function_name_prefix = GetFunctionNamePrefix(message);
395     FQName fqname = GetFQName(message);
396     out << "android::vts::DriverBase* " << function_name_prefix << "with_arg("
397         << "uint64_t hw_binder_proxy) {\n";
398     out.indent();
399     out << fqname.cppName() << "* arg = nullptr;\n";
400     out << "if (hw_binder_proxy) {\n";
401     out.indent();
402     out << "arg = reinterpret_cast<" << fqname.cppName()
403         << "*>(hw_binder_proxy);\n";
404     out.unindent();
405     out << "} else {\n";
406     out.indent();
407     out << "LOG(INFO) << \" Creating DriverBase with null proxy.\";\n";
408     out.unindent();
409     out << "}\n";
410     out << "android::vts::DriverBase* result ="
411         << "\n"
412         << "    new android::vts::" << fuzzer_extended_class_name << "(\n"
413         << "        arg);\n";
414     out << "if (arg != nullptr) {\n";
415     out.indent();
416     out << "arg->decStrong(arg);" << "\n";
417     out.unindent();
418     out << "}\n";
419     out << "return result;" << "\n";
420     out.unindent();
421     out << "}\n\n";
422     if (print_extern_block) {
423       out << "}" << "\n";
424     }
425   }
426 }
427 
GenerateClassHeader(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)428 void HalHidlCodeGen::GenerateClassHeader(Formatter& out,
429     const ComponentSpecificationMessage& message,
430     const string& fuzzer_extended_class_name) {
431   if (message.component_name() != "types") {
432     for (const auto& attribute : message.interface().attribute()) {
433       GenerateAllFunctionDeclForAttribute(out, attribute);
434     }
435     DriverCodeGenBase::GenerateClassHeader(out, message,
436                                            fuzzer_extended_class_name);
437   } else {
438     for (const auto& attribute : message.attribute()) {
439       GenerateAllFunctionDeclForAttribute(out, attribute);
440     };
441   }
442 }
443 
GenerateHeaderInterfaceImpl(Formatter & out,const ComponentSpecificationMessage & message)444 void HalHidlCodeGen::GenerateHeaderInterfaceImpl(
445     Formatter& out, const ComponentSpecificationMessage& message) {
446   out << "\n";
447   FQName component_fq_name = GetFQName(message);
448   string component_name_token = "Vts_" + component_fq_name.tokenName();
449   out << "class " << component_name_token << " : public "
450       << component_fq_name.cppName() << ", public DriverCallbackBase {\n";
451   out << " public:\n";
452   out.indent();
453   out << component_name_token << "(const string& callback_socket_name)\n"
454       << "    : callback_socket_name_(callback_socket_name) {};\n\n";
455   out << "virtual ~" << component_name_token << "()"
456       << " = default;\n\n";
457   for (const auto& api : message.interface().api()) {
458     // Generate return statement.
459     if (CanElideCallback(api)) {
460       out << "::android::hardware::Return<"
461           << GetCppVariableType(api.return_type_hidl(0)) << "> ";
462     } else {
463       out << "::android::hardware::Return<void> ";
464     }
465     // Generate function call.
466     out << api.name() << "(\n";
467     out.indent();
468     for (int index = 0; index < api.arg_size(); index++) {
469       const auto& arg = api.arg(index);
470       out << GetCppVariableType(arg, IsConstType(arg.type())) << " arg"
471           << index;
472       if (index != (api.arg_size() - 1)) out << ",\n";
473     }
474     if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
475       out << ") override;\n\n";
476     } else {  // handle the case of callbacks.
477       out << (api.arg_size() != 0 ? ", " : "");
478       out << "std::function<void(";
479       for (int index = 0; index < api.return_type_hidl_size(); index++) {
480         const auto& return_val = api.return_type_hidl(index);
481         out << GetCppVariableType(return_val, IsConstType(return_val.type()))
482             << " arg" << index;
483         if (index != (api.return_type_hidl_size() - 1)) out << ",";
484       }
485       out << ")> cb) override;\n\n";
486     }
487     out.unindent();
488   }
489   out << "\n";
490   out.unindent();
491   out << " private:\n";
492   out.indent();
493   out << "string callback_socket_name_;\n";
494   out.unindent();
495   out << "};\n\n";
496 
497   out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
498       << component_name_token << "(const string& callback_socket_name);\n\n";
499 }
500 
GenerateClassImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)501 void HalHidlCodeGen::GenerateClassImpl(Formatter& out,
502     const ComponentSpecificationMessage& message,
503     const string& fuzzer_extended_class_name) {
504   if (message.component_name() != "types") {
505     for (const auto& attribute : message.interface().attribute()) {
506       GenerateAllFunctionImplForAttribute(out, attribute);
507     }
508     GenerateGetServiceImpl(out, message, fuzzer_extended_class_name);
509     DriverCodeGenBase::GenerateClassImpl(out, message,
510                                          fuzzer_extended_class_name);
511   } else {
512     for (const auto& attribute : message.attribute()) {
513       GenerateAllFunctionImplForAttribute(out, attribute);
514     }
515   }
516 }
517 
GenerateHeaderIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)518 void HalHidlCodeGen::GenerateHeaderIncludeFiles(Formatter& out,
519     const ComponentSpecificationMessage& message,
520     const string& fuzzer_extended_class_name) {
521   DriverCodeGenBase::GenerateHeaderIncludeFiles(out, message,
522                                                 fuzzer_extended_class_name);
523   out << "#include <" << GetPackagePath(message) << "/" << GetVersion(message)
524       << "/" << GetComponentName(message) << ".h>"
525       << "\n";
526   out << "#include <hidl/HidlSupport.h>" << "\n";
527 
528   for (const auto& import : message.import()) {
529     FQName import_name;
530     if (!FQName::parse(import, &import_name)) {
531       abort();
532     }
533 
534     string import_package_name = import_name.package();
535     string import_package_version = import_name.version();
536     string import_component_name = import_name.name();
537     string import_package_path = import_package_name;
538     ReplaceSubString(import_package_path, ".", "/");
539 
540     out << "#include <" << import_package_path << "/" << import_package_version
541         << "/" << import_component_name << ".h>\n";
542     // Exclude the base hal in include list.
543     if (import_package_name.find("android.hidl.base") == std::string::npos) {
544       if (import_component_name[0] == 'I') {
545         import_component_name = import_component_name.substr(1);
546       }
547       out << "#include <" << import_package_path << "/"
548           << import_package_version << "/" << import_component_name
549           << ".vts.h>\n";
550     }
551   }
552 
553   out << "\n\n";
554 }
555 
GenerateSourceIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)556 void HalHidlCodeGen::GenerateSourceIncludeFiles(Formatter& out,
557     const ComponentSpecificationMessage& message,
558     const string& fuzzer_extended_class_name) {
559   DriverCodeGenBase::GenerateSourceIncludeFiles(out, message,
560                                                 fuzzer_extended_class_name);
561   out << "#include <android/hidl/allocator/1.0/IAllocator.h>\n";
562   out << "#include <fcntl.h>\n";
563   out << "#include <fmq/MessageQueue.h>\n";
564   out << "#include <sys/stat.h>\n";
565   out << "#include <unistd.h>\n";
566 }
567 
GenerateAdditionalFuctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message,const string &)568 void HalHidlCodeGen::GenerateAdditionalFuctionDeclarations(Formatter& out,
569     const ComponentSpecificationMessage& message,
570     const string& /*fuzzer_extended_class_name*/) {
571   if (message.component_name() != "types") {
572     out << "bool GetService(bool get_stub, const char* service_name);"
573         << "\n\n";
574   }
575 }
576 
GeneratePublicFunctionDeclarations(Formatter & out,const ComponentSpecificationMessage &)577 void HalHidlCodeGen::GeneratePublicFunctionDeclarations(
578     Formatter& out, const ComponentSpecificationMessage& /*message*/) {
579   out << "uint64_t GetHidlInterfaceProxy() const {\n";
580   out.indent();
581   out << "return reinterpret_cast<uintptr_t>(" << kInstanceVariableName
582       << ".get());\n";
583   out.unindent();
584   out << "}\n";
585 }
586 
GeneratePrivateMemberDeclarations(Formatter & out,const ComponentSpecificationMessage & message)587 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
588     const ComponentSpecificationMessage& message) {
589   FQName fqname = GetFQName(message);
590   out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
591 }
592 
GenerateRandomFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)593 void HalHidlCodeGen::GenerateRandomFunctionDeclForAttribute(Formatter& out,
594     const VariableSpecificationMessage& attribute) {
595   if (attribute.type() == TYPE_ENUM) {
596     if (attribute.enum_value().enumerator_size() == 0) {
597       // empty enum without any actual enumerator.
598       return;
599     }
600     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
601     out << attribute.enum_value().scalar_type() << " "
602         << "Random" << attribute_name << "();\n";
603   }
604 }
605 
GenerateRandomFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)606 void HalHidlCodeGen::GenerateRandomFunctionImplForAttribute(Formatter& out,
607     const VariableSpecificationMessage& attribute) {
608   // Random value generator
609   if (attribute.type() == TYPE_ENUM) {
610     if (attribute.enum_value().enumerator_size() == 0) {
611       // empty enum without any actual enumerator.
612       return;
613     }
614     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
615     out << attribute.enum_value().scalar_type() << " Random" << attribute_name
616         << "() {\n";
617     out.indent();
618     out << attribute.enum_value().scalar_type() << " choice = " << "("
619         << attribute.enum_value().scalar_type() << ") " << "rand() / "
620         << attribute.enum_value().enumerator().size() << ";" << "\n";
621     if (attribute.enum_value().scalar_type().find("u") != 0) {
622       out << "if (choice < 0) choice *= -1;" << "\n";
623     }
624     for (int index = 0; index < attribute.enum_value().enumerator().size();
625         index++) {
626       out << "if (choice == ";
627       out << "(" << attribute.enum_value().scalar_type() << ") ";
628       if (attribute.enum_value().scalar_type() == "int8_t") {
629         out << attribute.enum_value().scalar_value(index).int8_t();
630       } else if (attribute.enum_value().scalar_type() == "uint8_t") {
631         out << attribute.enum_value().scalar_value(index).uint8_t() << "U";
632       } else if (attribute.enum_value().scalar_type() == "int16_t") {
633         out << attribute.enum_value().scalar_value(index).int16_t();
634       } else if (attribute.enum_value().scalar_type() == "uint16_t") {
635         out << attribute.enum_value().scalar_value(index).uint16_t() << "U";
636       } else if (attribute.enum_value().scalar_type() == "int32_t") {
637         out << attribute.enum_value().scalar_value(index).int32_t() << "L";
638       } else if (attribute.enum_value().scalar_type() == "uint32_t") {
639         out << attribute.enum_value().scalar_value(index).uint32_t() << "UL";
640       } else if (attribute.enum_value().scalar_type() == "int64_t") {
641         if (attribute.enum_value().scalar_value(index).int64_t() == LLONG_MIN) {
642           out << "LLONG_MIN";
643         } else {
644           out << attribute.enum_value().scalar_value(index).int64_t() << "LL";
645         }
646       } else if (attribute.enum_value().scalar_type() == "uint64_t") {
647         out << attribute.enum_value().scalar_value(index).uint64_t() << "ULL";
648       } else {
649         cerr << __func__ << ":" << __LINE__ << " ERROR unsupported enum type "
650             << attribute.enum_value().scalar_type() << "\n";
651         exit(-1);
652       }
653       out << ") return static_cast<" << attribute.enum_value().scalar_type()
654           << ">(" << attribute.name()
655           << "::" << attribute.enum_value().enumerator(index) << ");\n";
656     }
657     out << "return static_cast<" << attribute.enum_value().scalar_type() << ">("
658         << attribute.name() << "::" << attribute.enum_value().enumerator(0)
659         << ");\n";
660     out.unindent();
661     out << "}" << "\n";
662   }
663 }
664 
GenerateDriverDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)665 void HalHidlCodeGen::GenerateDriverDeclForAttribute(Formatter& out,
666     const VariableSpecificationMessage& attribute) {
667   if (!IsUserDefinedType(attribute.type())) {
668     cerr << attribute.type() << " is not a user defined type\n";
669     exit(-1);
670   }
671   for (const auto& sub_struct : attribute.sub_struct()) {
672     GenerateDriverDeclForAttribute(out, sub_struct);
673   }
674   for (const auto& sub_union : attribute.sub_union()) {
675     GenerateDriverDeclForAttribute(out, sub_union);
676   }
677   for (const auto& sub_safe_union : attribute.sub_safe_union()) {
678     GenerateDriverDeclForAttribute(out, sub_safe_union);
679   }
680   string func_name =
681       "MessageTo" + ClearStringWithNameSpaceAccess(attribute.name());
682   // Add extern C to allow resource_manager to dynamically load this function.
683   out << "extern \"C\" ";
684   out << "void " << func_name
685       << "(const VariableSpecificationMessage& var_msg, " << attribute.name()
686       << "* arg, const string& callback_socket_name);\n";
687 }
688 
GenerateDriverImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)689 void HalHidlCodeGen::GenerateDriverImplForAttribute(Formatter& out,
690     const VariableSpecificationMessage& attribute) {
691   if (!IsUserDefinedType(attribute.type())) {
692     cerr << attribute.type() << " is not a user defined type\n";
693     exit(-1);
694   }
695   // Recursively generate driver implementation method for all sub_types.
696   for (const auto& sub_struct : attribute.sub_struct()) {
697     GenerateDriverImplForAttribute(out, sub_struct);
698   }
699   for (const auto& sub_union : attribute.sub_union()) {
700     GenerateDriverImplForAttribute(out, sub_union);
701   }
702   for (const auto& sub_safe_union : attribute.sub_safe_union()) {
703     GenerateDriverImplForAttribute(out, sub_safe_union);
704   }
705   string func_name =
706       "MessageTo" + ClearStringWithNameSpaceAccess(attribute.name());
707   // Add extern C to allow resource_manager to dynamically load this
708   // function.
709   out << "extern \"C\" ";
710   out << "void " << func_name
711       << "(const VariableSpecificationMessage& "
712          "var_msg __attribute__((__unused__)), "
713       << attribute.name() << "* arg __attribute__((__unused__)), "
714       << "const string& callback_socket_name __attribute__((__unused__))) {"
715       << "\n";
716   out.indent();
717 
718   switch (attribute.type()) {
719     case TYPE_ENUM: {
720       out << "*arg = (" << attribute.name() << ")var_msg.scalar_value()."
721           << attribute.enum_value().scalar_type() << "();\n";
722       break;
723     }
724     case TYPE_STRUCT: {
725       int struct_index = 0;
726       for (const auto& struct_value : attribute.struct_value()) {
727         GenerateDriverImplForTypedVariable(
728             out, struct_value, "arg->" + struct_value.name(),
729             "var_msg.struct_value(" + std::to_string(struct_index) + ")");
730         struct_index++;
731       }
732       break;
733     }
734     case TYPE_UNION: {
735       int union_index = 0;
736       for (const auto& union_value : attribute.union_value()) {
737         out << "if (var_msg.union_value(" << union_index << ").name() == \""
738             << union_value.name() << "\") {"
739             << "\n";
740         out.indent();
741         GenerateDriverImplForTypedVariable(
742             out, union_value, "arg->" + union_value.name(),
743             "var_msg.union_value(" + std::to_string(union_index) + ")");
744         union_index++;
745         out.unindent();
746         out << "}\n";
747       }
748       break;
749     }
750     case TYPE_SAFE_UNION: {
751       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
752       break;
753     }
754     default: {
755       cerr << __func__ << " unsupported attribute type " << attribute.type()
756            << "\n";
757       exit(-1);
758     }
759   }
760   out.unindent();
761   out << "}\n";
762 }
763 
GenerateGetServiceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)764 void HalHidlCodeGen::GenerateGetServiceImpl(Formatter& out,
765     const ComponentSpecificationMessage& message,
766     const string& fuzzer_extended_class_name) {
767   out << "bool " << fuzzer_extended_class_name
768       << "::GetService(bool get_stub, const char* service_name) {" << "\n";
769   out.indent();
770   out << "static bool initialized = false;" << "\n";
771   out << "if (!initialized) {" << "\n";
772   out.indent();
773   out << "LOG(INFO) << \"HIDL getService\";"
774       << "\n";
775   out << "if (service_name) {\n"
776       << "  LOG(INFO) << \"  - service name: \" << service_name;"
777       << "\n"
778       << "}\n";
779   FQName fqname = GetFQName(message);
780   out << kInstanceVariableName << " = " << fqname.cppName() << "::getService("
781       << "service_name, get_stub);" << "\n";
782   out << "if (" << kInstanceVariableName << " == nullptr) {\n";
783   out.indent();
784   out << "LOG(ERROR) << \"getService() returned a null pointer.\";\n";
785   out << "return false;\n";
786   out.unindent();
787   out << "}\n";
788   out << "LOG(DEBUG) << \"" << kInstanceVariableName << " = \" << "
789       << kInstanceVariableName << ".get();"
790       << "\n";
791   out << "initialized = true;" << "\n";
792   out.unindent();
793   out << "}" << "\n";
794   out << "return true;" << "\n";
795   out.unindent();
796   out << "}" << "\n" << "\n";
797 }
798 
GenerateDriverImplForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & arg_name,const string & arg_value_name)799 void HalHidlCodeGen::GenerateDriverImplForTypedVariable(Formatter& out,
800     const VariableSpecificationMessage& val, const string& arg_name,
801     const string& arg_value_name) {
802   switch (val.type()) {
803     case TYPE_SCALAR:
804     {
805       out << arg_name << " = " << arg_value_name << ".scalar_value()."
806           << val.scalar_type() << "();\n";
807       break;
808     }
809     case TYPE_STRING:
810     {
811       out << arg_name << " = ::android::hardware::hidl_string("
812           << arg_value_name << ".string_value().message());\n";
813       break;
814     }
815     case TYPE_ENUM:
816     {
817       if (val.has_predefined_type()) {
818         string func_name =
819             "MessageTo" + ClearStringWithNameSpaceAccess(val.predefined_type());
820         out << func_name << "(" << arg_value_name << ", &(" << arg_name
821             << "), callback_socket_name);\n";
822       } else {
823         out << arg_name << " = (" << val.name() << ")" << arg_value_name << "."
824             << "enum_value().scalar_value(0)." << val.enum_value().scalar_type()
825             << "();\n";
826       }
827       break;
828     }
829     case TYPE_MASK:
830     {
831       out << arg_name << " = " << arg_value_name << ".scalar_value()."
832           << val.scalar_type() << "();\n";
833       break;
834     }
835     case TYPE_VECTOR:
836     {
837       out << arg_name << ".resize(" << arg_value_name
838           << ".vector_value_size());\n";
839       std::string index_name = GetVarString(arg_name) + "_index";
840       out << "for (int " << index_name << " = 0; " << index_name << " < "
841           << arg_value_name << ".vector_value_size(); " << index_name
842           << "++) {\n";
843       out.indent();
844       GenerateDriverImplForTypedVariable(
845           out, val.vector_value(0), arg_name + "[" + index_name + "]",
846           arg_value_name + ".vector_value(" + index_name + ")");
847       out.unindent();
848       out << "}\n";
849       break;
850     }
851     case TYPE_ARRAY:
852     {
853       std::string index_name = GetVarString(arg_name) + "_index";
854       out << "for (int " << index_name << " = 0; " << index_name << " < "
855           << arg_value_name << ".vector_value_size(); " << index_name
856           << "++) {\n";
857       out.indent();
858       GenerateDriverImplForTypedVariable(
859           out, val.vector_value(0), arg_name + "[" + index_name + "]",
860           arg_value_name + ".vector_value(" + index_name + ")");
861       out.unindent();
862       out << "}\n";
863       break;
864     }
865     case TYPE_STRUCT:
866     {
867       if (val.has_predefined_type()) {
868         string func_name = "MessageTo"
869             + ClearStringWithNameSpaceAccess(val.predefined_type());
870         out << func_name << "(" << arg_value_name << ", &(" << arg_name
871             << "), callback_socket_name);\n";
872       } else {
873         int struct_index = 0;
874         for (const auto& struct_field : val.struct_value()) {
875           string struct_field_name = arg_name + "." + struct_field.name();
876           string struct_field_value_name = arg_value_name + ".struct_value("
877               + std::to_string(struct_index) + ")";
878           GenerateDriverImplForTypedVariable(out, struct_field,
879                                              struct_field_name,
880                                              struct_field_value_name);
881           struct_index++;
882         }
883       }
884       break;
885     }
886     case TYPE_UNION:
887     {
888       if (val.has_predefined_type()) {
889         string func_name = "MessageTo"
890             + ClearStringWithNameSpaceAccess(val.predefined_type());
891         out << func_name << "(" << arg_value_name << ", &(" << arg_name
892             << "), callback_socket_name);\n";
893       } else {
894         int union_index = 0;
895         for (const auto& union_field : val.union_value()) {
896           string union_field_name = arg_name + "." + union_field.name();
897           string union_field_value_name = arg_value_name + ".union_value("
898               + std::to_string(union_index) + ")";
899           GenerateDriverImplForTypedVariable(out, union_field, union_field_name,
900                                              union_field_value_name);
901           union_index++;
902         }
903       }
904       break;
905     }
906     case TYPE_HIDL_CALLBACK:
907     {
908       string type_name = val.predefined_type();
909       ReplaceSubString(type_name, "::", "_");
910 
911       out << arg_name << " = VtsFuzzerCreateVts" << type_name
912           << "(callback_socket_name);\n";
913       out << "static_cast<" << "Vts" + type_name << "*>(" << arg_name
914           << ".get())->Register(" << arg_value_name << ");\n";
915       break;
916     }
917     case TYPE_HANDLE:
918     {
919       out << "if (" << arg_value_name << ".has_handle_value()) {\n";
920       out.indent();
921       out << "if (" << arg_value_name
922           << ".handle_value().has_hidl_handle_address()) {\n";
923       out.indent();  // if case starts: existing hidl_handle is specified.
924       out << arg_name
925           << " = *(reinterpret_cast<android::hardware::hidl_handle*>("
926           << arg_value_name << ".handle_value().hidl_handle_address()));\n";
927       out.unindent();  // if case ends.
928       out << "} else {\n";
929       out.indent();  // else case starts: create a new handle object.
930       out << "native_handle_t* handle = native_handle_create(" << arg_value_name
931           << ".handle_value().num_fds(), " << arg_value_name
932           << ".handle_value().num_ints());\n";
933       out << "if (!handle) {\n";
934       out.indent();
935       out << "LOG(ERROR) << \"Failed to create handle. \";\n";
936       out << "exit(-1);\n";
937       out.unindent();
938       out << "}\n";
939       out << "for (int fd_index = 0; fd_index < " << arg_value_name
940           << ".handle_value().num_fds() + " << arg_value_name
941           << ".handle_value().num_ints(); fd_index++) {\n";
942       out.indent();
943       out << "if (fd_index < " << arg_value_name
944           << ".handle_value().num_fds()) {\n";
945       out.indent();
946       out << "FdMessage fd_val = " << arg_value_name
947           << ".handle_value().fd_val(fd_index);\n";
948       out << "string file_name = fd_val.file_name();\n";
949       out << "switch (fd_val.type()) {\n";
950       out.indent();
951       out << "case FdType::FILE_TYPE:\n";
952       out << "{\n";
953       out.indent();
954       // Create the parent path recursively if not exist.
955       out << "size_t pre = 0; size_t pos = 0;\n";
956       out << "string dir;\n";
957       out << "struct stat st;\n";
958       out << "while((pos=file_name.find_first_of('/', pre)) "
959           << "!= string::npos){\n";
960       out.indent();
961       out << "dir = file_name.substr(0, pos++);\n";
962       out << "pre = pos;\n";
963       out << "if(dir.size() == 0) continue; // ignore leading /\n";
964       out << "if (stat(dir.c_str(), &st) == -1) {\n";
965       out << "LOG(INFO) << \" Creating dir: \" << dir;\n";
966       out.indent();
967       out << "mkdir(dir.c_str(), 0700);\n";
968       out.unindent();
969       out << "}\n";
970       out.unindent();
971       out << "}\n";
972       out << "int fd = open(file_name.c_str(), "
973           << "fd_val.flags() | O_CREAT, fd_val.mode());\n";
974       out << "if (fd == -1) {\n";
975       out.indent();
976       out << "LOG(ERROR) << \"Failed to open file: \" << file_name << \" "
977              "error: \" << errno;\n";
978       out << "exit (-1);\n";
979       out.unindent();
980       out << "}\n";
981       out << "handle->data[fd_index] = fd;\n";
982       out << "break;\n";
983       out.unindent();
984       out << "}\n";
985       out << "case FdType::DIR_TYPE:\n";
986       out << "{\n";
987       out.indent();
988       out << "struct stat st;\n";
989       out << "if (!stat(file_name.c_str(), &st)) {\n";
990       out.indent();
991       out << "mkdir(file_name.c_str(), fd_val.mode());\n";
992       out.unindent();
993       out << "}\n";
994       out << "handle->data[fd_index] = open(file_name.c_str(), O_DIRECTORY, "
995           << "fd_val.mode());\n";
996       out << "break;\n";
997       out.unindent();
998       out << "}\n";
999       out << "case FdType::DEV_TYPE:\n";
1000       out << "{\n";
1001       out.indent();
1002       out << "if(file_name == \"/dev/ashmem\") {\n";
1003       out.indent();
1004       out << "handle->data[fd_index] = ashmem_create_region(\"SharedMemory\", "
1005           << "fd_val.memory().size());\n";
1006       out.unindent();
1007       out << "}\n";
1008       out << "break;\n";
1009       out.unindent();
1010       out << "}\n";
1011       out << "case FdType::PIPE_TYPE:\n";
1012       out << "case FdType::SOCKET_TYPE:\n";
1013       out << "case FdType::LINK_TYPE:\n";
1014       out << "{\n";
1015       out.indent();
1016       out << "LOG(ERROR) << \"Not supported yet. \";\n";
1017       out << "break;\n";
1018       out.unindent();
1019       out << "}\n";
1020       out.unindent();
1021       out << "}\n";
1022       out.unindent();
1023       out << "} else {\n";
1024       out.indent();
1025       out << "handle->data[fd_index] = " << arg_value_name
1026           << ".handle_value().int_val(fd_index -" << arg_value_name
1027           << ".handle_value().num_fds());\n";
1028       out.unindent();
1029       out << "}\n";
1030       out.unindent();
1031       out << "}\n";
1032       out << arg_name << " = handle;\n";
1033       out.unindent();  // else case (create a new handle object) ends.
1034       out << "}\n";
1035       out.unindent();
1036       out << "} else {\n";
1037       out.indent();
1038       out << arg_name << " = nullptr;\n";
1039       out.unindent();
1040       out << "}\n";
1041       break;
1042     }
1043     case TYPE_HIDL_INTERFACE:
1044     {
1045       string type_name = val.predefined_type();
1046       out << "if (" << arg_value_name << ".has_hidl_interface_pointer()) {\n";
1047       out.indent();
1048       out << arg_name << " = reinterpret_cast<" << type_name << "*>("
1049           << arg_value_name << ".hidl_interface_pointer());\n";
1050       out.unindent();
1051       out << "} else {\n";
1052       out.indent();
1053       if (type_name.find("::android::hidl") == 0) {
1054         out << "LOG(ERROR) << \"general interface is not supported yet. \";\n";
1055       } else {
1056         ReplaceSubString(type_name, "::", "_");
1057         out << arg_name << " = VtsFuzzerCreateVts" << type_name
1058             << "(callback_socket_name);\n";
1059       }
1060       out.unindent();
1061       out << "}\n";
1062       break;
1063     }
1064     case TYPE_HIDL_MEMORY:
1065     {
1066       out << "if (" << arg_value_name
1067           << ".hidl_memory_value().has_hidl_mem_address()) {\n";
1068       out.indent();  // if case starts: existing hidl_memory is used.
1069       out << arg_name
1070           << " = *(reinterpret_cast<android::hardware::hidl_memory*>("
1071           << arg_value_name << ".hidl_memory_value().hidl_mem_address()));\n";
1072       out.unindent();  // if case ends.
1073       out << "} else {\n";
1074       out.indent();  // else case starts: allocates new memory region.
1075       out << "sp<::android::hidl::allocator::V1_0::IAllocator> ashmemAllocator"
1076           << " = ::android::hidl::allocator::V1_0::IAllocator::getService(\""
1077           << "ashmem\");\n";
1078       out << "if (ashmemAllocator == nullptr) {\n";
1079       out.indent();
1080       out << "LOG(ERROR) << \"Failed to get ashmemAllocator! \";\n";
1081       out << "exit(-1);\n";
1082       out.unindent();
1083       out << "}\n";
1084       // TODO(zhuoyao): initialize memory with recorded contents.
1085       out << "auto res = ashmemAllocator->allocate(" << arg_value_name
1086           << ".hidl_memory_value().size(), [&](bool success, "
1087           << "const hardware::hidl_memory& memory) {\n";
1088       out.indent();
1089       out << "if (!success) {\n";
1090       out.indent();
1091       out << "LOG(ERROR) << \"Failed to allocate memory! \";\n";
1092       out << arg_name << " = ::android::hardware::hidl_memory();\n";
1093       out << "return;\n";
1094       out.unindent();
1095       out << "}\n";
1096       out << arg_name << " = memory;\n";
1097       out.unindent();
1098       out << "});\n";
1099       out.unindent();  // else case ends.
1100       out << "}\n";
1101       break;
1102     }
1103     case TYPE_POINTER:
1104     {
1105       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1106       break;
1107     }
1108     case TYPE_FMQ_SYNC:
1109     case TYPE_FMQ_UNSYNC: {
1110       if (arg_name.find("->") != std::string::npos) {
1111         out << "LOG(ERROR) << \"Nested structure with fmq is not supported "
1112                "yet. \";\n";
1113       } else {
1114         // TODO(zhuoyao): consider record and use the queue capacity.
1115         std::string element_type = GetCppVariableType(val.fmq_value(0));
1116         std::string queue_name =
1117             arg_name + (val.type() == TYPE_FMQ_SYNC ? "_sync_q" : "_unsync_q");
1118         std::string queue_descriptor_type = GetCppVariableType(val);
1119 
1120         // When caller wants to reuse an existing queue.
1121         out << "if (" << arg_value_name << ".fmq_value_size() > 0 && "
1122             << arg_value_name << ".fmq_value(0).has_fmq_desc_address()) {\n";
1123         out.indent();  // if case starts
1124         out << arg_name << " = "
1125             << "reinterpret_cast<" << queue_descriptor_type << "*>("
1126             << arg_value_name << ".fmq_value(0).fmq_desc_address());\n";
1127         out.unindent();  // if case ends
1128 
1129         // When caller wants to create a brand new queue and write to it.
1130         out << "} else {\n";
1131         out.indent();  // else case starts
1132         out << "::android::hardware::MessageQueue<" << element_type
1133             << ", ::android::hardware::"
1134             << (val.type() == TYPE_FMQ_SYNC ? "kSynchronizedReadWrite"
1135                                             : "kUnsynchronizedWrite")
1136             << "> " << queue_name << "(1024);\n";
1137         out << "for (int i = 0; i < (int)" << arg_value_name
1138             << ".fmq_value_size(); i++) {\n";
1139         out.indent();  // for loop starts
1140         std::string fmq_item_name = queue_name + "_item";
1141         out << element_type << " " << fmq_item_name << ";\n";
1142         GenerateDriverImplForTypedVariable(out, val.fmq_value(0), fmq_item_name,
1143                                            arg_value_name + ".fmq_value(i)");
1144         out << queue_name << ".write(&" << fmq_item_name << ");\n";
1145         out.unindent();  // for loop ends
1146         out << "}\n";
1147         out << arg_name << " = " << queue_name << ".getDesc();\n";
1148         out.unindent();  // else case ends
1149         out << "}\n";
1150       }
1151       break;
1152     }
1153     case TYPE_REF:
1154     {
1155       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1156       break;
1157     }
1158     case TYPE_SAFE_UNION: {
1159       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
1160       break;
1161     }
1162     default:
1163     {
1164       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1165       exit(-1);
1166     }
1167   }
1168 }
1169 
1170 // TODO(zhuoyao): Verify results based on verification rules instead of perform
1171 // an exact match.
GenerateVerificationFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)1172 void HalHidlCodeGen::GenerateVerificationFunctionImpl(Formatter& out,
1173     const ComponentSpecificationMessage& message,
1174     const string& fuzzer_extended_class_name) {
1175   if (message.component_name() != "types") {
1176     // Generate the main profiler function.
1177     out << "\nbool " << fuzzer_extended_class_name;
1178     out.indent();
1179     out << "::VerifyResults(const FunctionSpecificationMessage& "
1180            "expected_result __attribute__((__unused__)),"
1181         << "\n";
1182     out << "const FunctionSpecificationMessage& actual_result "
1183            "__attribute__((__unused__))) {\n";
1184     for (const FunctionSpecificationMessage& api : message.interface().api()) {
1185       out << "if (!strcmp(actual_result.name().c_str(), \"" << api.name()
1186           << "\")) {\n";
1187       out.indent();
1188       out << "if (actual_result.return_type_hidl_size() != "
1189           << "expected_result.return_type_hidl_size() "
1190           << ") { return false; }\n";
1191       for (int i = 0; i < api.return_type_hidl_size(); i++) {
1192         std::string expected_result = "expected_result.return_type_hidl("
1193             + std::to_string(i) + ")";
1194         std::string actual_result = "actual_result.return_type_hidl("
1195             + std::to_string(i) + ")";
1196         GenerateVerificationCodeForTypedVariable(out, api.return_type_hidl(i),
1197                                                  expected_result,
1198                                                  actual_result);
1199       }
1200       out << "return true;\n";
1201       out.unindent();
1202       out << "}\n";
1203     }
1204     out << "return false;\n";
1205     out.unindent();
1206     out << "}\n\n";
1207   }
1208 }
1209 
GenerateVerificationCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & expected_result,const string & actual_result)1210 void HalHidlCodeGen::GenerateVerificationCodeForTypedVariable(Formatter& out,
1211     const VariableSpecificationMessage& val, const string& expected_result,
1212     const string& actual_result) {
1213   switch (val.type()) {
1214     case TYPE_SCALAR:
1215     {
1216       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
1217           << "() != " << expected_result << ".scalar_value()."
1218           << val.scalar_type() << "()) { return false; }\n";
1219       break;
1220     }
1221     case TYPE_STRING:
1222     {
1223       out << "if (strcmp(" << actual_result
1224           << ".string_value().message().c_str(), " << expected_result
1225           << ".string_value().message().c_str())!= 0)" << "{ return false; }\n";
1226       break;
1227     }
1228     case TYPE_ENUM:
1229     {
1230       if (val.has_predefined_type()) {
1231         string func_name = "Verify"
1232             + ClearStringWithNameSpaceAccess(val.predefined_type());
1233         out << "if(!" << func_name << "(" << expected_result << ", "
1234             << actual_result << ")) { return false; }\n";
1235       } else {
1236         out << "if (" << actual_result << ".scalar_value()."
1237             << val.enum_value().scalar_type() << "() != " << expected_result
1238             << ".scalar_value()." << val.enum_value().scalar_type()
1239             << "()) { return false; }\n";
1240       }
1241       break;
1242     }
1243     case TYPE_MASK:
1244     {
1245       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
1246           << "() != " << expected_result << ".scalar_value()."
1247           << val.scalar_type() << "()) { return false; }\n";
1248       break;
1249     }
1250     case TYPE_VECTOR:
1251     {
1252       out << "if (" << actual_result << ".vector_value_size() != "
1253           << expected_result << ".vector_value_size()) {\n";
1254       out.indent();
1255       out << "LOG(ERROR) << \"Verification failed for vector size. expected: "
1256              "\" << "
1257           << expected_result << ".vector_value_size() << \" actual: \" << "
1258           << actual_result << ".vector_value_size();\n";
1259       out << "return false;\n";
1260       out.unindent();
1261       out << "}\n";
1262       out << "for (int i = 0; i <" << expected_result
1263           << ".vector_value_size(); i++) {\n";
1264       out.indent();
1265       GenerateVerificationCodeForTypedVariable(
1266           out, val.vector_value(0), expected_result + ".vector_value(i)",
1267           actual_result + ".vector_value(i)");
1268       out.unindent();
1269       out << "}\n";
1270       break;
1271     }
1272     case TYPE_ARRAY:
1273     {
1274       out << "if (" << actual_result << ".vector_value_size() != "
1275           << expected_result << ".vector_value_size()) {\n";
1276       out.indent();
1277       out << "LOG(ERROR) << \"Verification failed for vector size. expected: "
1278              "\" << "
1279           << expected_result << ".vector_value_size() << \" actual: \" << "
1280           << actual_result << ".vector_value_size();\n";
1281       out << "return false;\n";
1282       out.unindent();
1283       out << "}\n";
1284       out << "for (int i = 0; i < " << expected_result
1285           << ".vector_value_size(); i++) {\n";
1286       out.indent();
1287       GenerateVerificationCodeForTypedVariable(
1288           out, val.vector_value(0), expected_result + ".vector_value(i)",
1289           actual_result + ".vector_value(i)");
1290       out.unindent();
1291       out << "}\n";
1292       break;
1293     }
1294     case TYPE_STRUCT:
1295     {
1296       if (val.has_predefined_type()) {
1297         string func_name = "Verify"
1298             + ClearStringWithNameSpaceAccess(val.predefined_type());
1299         out << "if (!" << func_name << "(" << expected_result << ", "
1300             << actual_result << ")) { return false; }\n";
1301       } else {
1302         for (int i = 0; i < val.struct_value_size(); i++) {
1303           string struct_field_actual_result = actual_result + ".struct_value("
1304               + std::to_string(i) + ")";
1305           string struct_field_expected_result = expected_result
1306               + ".struct_value(" + std::to_string(i) + ")";
1307           GenerateVerificationCodeForTypedVariable(out, val.struct_value(i),
1308                                                    struct_field_expected_result,
1309                                                    struct_field_actual_result);
1310         }
1311       }
1312       break;
1313     }
1314     case TYPE_UNION:
1315     {
1316       if (val.has_predefined_type()) {
1317         string func_name = "Verify"
1318             + ClearStringWithNameSpaceAccess(val.predefined_type());
1319         out << "if (!" << func_name << "(" << expected_result << ", "
1320             << actual_result << ")) {return false; }\n";
1321       } else {
1322         for (int i = 0; i < val.union_value_size(); i++) {
1323           string union_field_actual_result = actual_result + ".union_value("
1324               + std::to_string(i) + ")";
1325           string union_field_expected_result = expected_result + ".union_value("
1326               + std::to_string(i) + ")";
1327           GenerateVerificationCodeForTypedVariable(out, val.union_value(i),
1328                                                    union_field_expected_result,
1329                                                    union_field_actual_result);
1330         }
1331       }
1332       break;
1333     }
1334     case TYPE_HIDL_CALLBACK:
1335     {
1336       out << "LOG(ERROR) << \"TYPE_HILD_CALLBACK is not supported yet. \";\n";
1337       break;
1338     }
1339     case TYPE_HANDLE:
1340     {
1341       out << "LOG(ERROR) << \"TYPE_HANDLE is not supported yet. \";\n";
1342       break;
1343     }
1344     case TYPE_HIDL_INTERFACE:
1345     {
1346       out << "LOG(ERROR) << \"TYPE_HIDL_INTERFACE is not supported yet. \";\n";
1347       break;
1348     }
1349     case TYPE_HIDL_MEMORY:
1350     {
1351       out << "LOG(ERROR) << \"TYPE_HIDL_MEMORY is not supported yet. \";\n";
1352       break;
1353     }
1354     case TYPE_POINTER:
1355     {
1356       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1357       break;
1358     }
1359     case TYPE_FMQ_SYNC:
1360     {
1361       out << "LOG(ERROR) << \"TYPE_FMQ_SYNC is not supported yet. \";\n";
1362       break;
1363     }
1364     case TYPE_FMQ_UNSYNC:
1365     {
1366       out << "LOG(ERROR) << \"TYPE_FMQ_UNSYNC is not supported yet. \";\n";
1367       break;
1368     }
1369     case TYPE_REF:
1370     {
1371       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1372       break;
1373     }
1374     case TYPE_SAFE_UNION: {
1375       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is Not supported yet. \";\n";
1376       break;
1377     }
1378     default:
1379     {
1380       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1381       exit(-1);
1382     }
1383   }
1384 }
1385 
GenerateVerificationDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1386 void HalHidlCodeGen::GenerateVerificationDeclForAttribute(Formatter& out,
1387     const VariableSpecificationMessage& attribute) {
1388   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1389     // Recursively generate verification method implementation for all sub_types.
1390     for (const auto& sub_struct : attribute.sub_struct()) {
1391       GenerateVerificationDeclForAttribute(out, sub_struct);
1392     }
1393     for (const auto& sub_union : attribute.sub_union()) {
1394       GenerateVerificationDeclForAttribute(out, sub_union);
1395     }
1396   }
1397   std::string func_name = "bool Verify"
1398       + ClearStringWithNameSpaceAccess(attribute.name());
1399   out << func_name << "(const VariableSpecificationMessage& expected_result, "
1400       << "const VariableSpecificationMessage& actual_result);\n";
1401 }
1402 
GenerateVerificationImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1403 void HalHidlCodeGen::GenerateVerificationImplForAttribute(Formatter& out,
1404     const VariableSpecificationMessage& attribute) {
1405   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1406     // Recursively generate verification method implementation for all sub_types.
1407     for (const auto& sub_struct : attribute.sub_struct()) {
1408       GenerateVerificationImplForAttribute(out, sub_struct);
1409     }
1410     for (const auto& sub_union : attribute.sub_union()) {
1411       GenerateVerificationImplForAttribute(out, sub_union);
1412     }
1413   }
1414   std::string func_name = "bool Verify"
1415       + ClearStringWithNameSpaceAccess(attribute.name());
1416   out << func_name << "(const VariableSpecificationMessage& expected_result "
1417                       "__attribute__((__unused__)), "
1418       << "const VariableSpecificationMessage& actual_result "
1419          "__attribute__((__unused__))){\n";
1420   out.indent();
1421   GenerateVerificationCodeForTypedVariable(out, attribute, "expected_result",
1422                                            "actual_result");
1423   out << "return true;\n";
1424   out.unindent();
1425   out << "}\n\n";
1426 }
1427 
1428 // TODO(zhuoyao): consider to generalize the pattern for
1429 // Verification/SetResult/DriverImpl.
GenerateSetResultCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & result_msg,const string & result_value)1430 void HalHidlCodeGen::GenerateSetResultCodeForTypedVariable(Formatter& out,
1431     const VariableSpecificationMessage& val, const string& result_msg,
1432     const string& result_value) {
1433   switch (val.type()) {
1434     case TYPE_SCALAR:
1435     {
1436       out << result_msg << "->set_type(TYPE_SCALAR);\n";
1437       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1438           << "\");\n";
1439       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1440           << "(" << result_value << ");\n";
1441       break;
1442     }
1443     case TYPE_STRING:
1444     {
1445       out << result_msg << "->set_type(TYPE_STRING);\n";
1446       out << result_msg << "->mutable_string_value()->set_message" << "("
1447           << result_value << ".c_str());\n";
1448       out << result_msg << "->mutable_string_value()->set_length" << "("
1449           << result_value << ".size());\n";
1450       break;
1451     }
1452     case TYPE_ENUM:
1453     {
1454       out << result_msg << "->set_type(TYPE_ENUM);\n";
1455       if (val.has_predefined_type()) {
1456         string func_name = "SetResult"
1457             + ClearStringWithNameSpaceAccess(val.predefined_type());
1458         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1459       } else {
1460         const string scalar_type = val.enum_value().scalar_type();
1461         out << result_msg << "->set_scalar_type(\"" << scalar_type << "\");\n";
1462         out << result_msg << "->mutable_scalar_value()->set_" << scalar_type
1463             << "(static_cast<" << scalar_type << ">(" << result_value
1464             << "));\n";
1465       }
1466       break;
1467     }
1468     case TYPE_MASK:
1469     {
1470       out << result_msg << "->set_type(TYPE_MASK);\n";
1471       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1472           << "\");\n";
1473       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1474           << "(" << result_value << ");\n";
1475       break;
1476     }
1477     case TYPE_VECTOR:
1478     {
1479       out << result_msg << "->set_type(TYPE_VECTOR);\n";
1480       out << result_msg << "->set_vector_size(" << result_value
1481           << ".size());\n";
1482       out << "for (int i = 0; i < (int)" << result_value << ".size(); i++) {\n";
1483       out.indent();
1484       string vector_element_name = result_msg + "_vector_i";
1485       out << "auto *" << vector_element_name << " = " << result_msg
1486           << "->add_vector_value();\n";
1487       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1488                                             vector_element_name,
1489                                             result_value + "[i]");
1490       out.unindent();
1491       out << "}\n";
1492       break;
1493     }
1494     case TYPE_ARRAY:
1495     {
1496       out << result_msg << "->set_type(TYPE_ARRAY);\n";
1497       out << result_msg << "->set_vector_size(" << val.vector_value_size()
1498           << ");\n";
1499       out << "for (int i = 0; i < " << val.vector_value_size() << "; i++) {\n";
1500       out.indent();
1501       string array_element_name = result_msg + "_array_i";
1502       out << "auto *" << array_element_name << " = " << result_msg
1503           << "->add_vector_value();\n";
1504       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1505                                             array_element_name,
1506                                             result_value + "[i]");
1507       out.unindent();
1508       out << "}\n";
1509       break;
1510     }
1511     case TYPE_STRUCT:
1512     {
1513       out << result_msg << "->set_type(TYPE_STRUCT);\n";
1514       if (val.has_predefined_type()) {
1515         string func_name = "SetResult"
1516             + ClearStringWithNameSpaceAccess(val.predefined_type());
1517         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1518       } else {
1519         for (const auto& struct_field : val.struct_value()) {
1520           string struct_field_name = result_msg + "_" + struct_field.name();
1521           out << "auto *" << struct_field_name << " = " << result_msg
1522               << "->add_struct_value();\n";
1523           GenerateSetResultCodeForTypedVariable(
1524               out, struct_field, struct_field_name,
1525               result_value + "." + struct_field.name());
1526           if (struct_field.has_name()) {
1527             out << struct_field_name << "->set_name(\""
1528                 << struct_field.name() << "\");\n";
1529           }
1530         }
1531       }
1532       break;
1533     }
1534     case TYPE_UNION:
1535     {
1536       out << result_msg << "->set_type(TYPE_UNION);\n";
1537       if (val.has_predefined_type()) {
1538         string func_name = "SetResult"
1539             + ClearStringWithNameSpaceAccess(val.predefined_type());
1540         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1541       } else {
1542         for (const auto& union_field : val.union_value()) {
1543           string union_field_name = result_msg + "_" + union_field.name();
1544           out << "auto *" << union_field_name << " = " << result_msg
1545               << "->add_union_value();\n";
1546           GenerateSetResultCodeForTypedVariable(
1547               out, union_field, union_field_name,
1548               result_value + "." + union_field.name());
1549           if (union_field.has_name()) {
1550             out << union_field_name << "->set_name(\"" << union_field.name()
1551                 << "\");\n";
1552           }
1553         }
1554       }
1555       break;
1556     }
1557     case TYPE_HIDL_CALLBACK:
1558     {
1559       out << result_msg << "->set_type(TYPE_HIDL_CALLBACK);\n";
1560       out << "LOG(ERROR) << \"TYPE HIDL_CALLBACK is not supported yet. \";\n";
1561       break;
1562     }
1563     case TYPE_HANDLE:
1564     {
1565       out << result_msg << "->set_type(TYPE_HANDLE);\n";
1566       out << result_msg << "->mutable_handle_value()->set_hidl_handle_address"
1567           << "(reinterpret_cast<size_t>(new android::hardware::hidl_handle("
1568           << result_value << ")));\n";
1569       break;
1570     }
1571     case TYPE_HIDL_INTERFACE:
1572     {
1573       out << result_msg << "->set_type(TYPE_HIDL_INTERFACE);\n";
1574       if (!val.has_predefined_type()) {
1575         cerr << __func__ << ":" << __LINE__
1576              << " HIDL interface is a return type"
1577              << "but predefined_type is unset." << endl;
1578         exit(-1);
1579       }
1580       out << result_msg << "->set_predefined_type(\"" << val.predefined_type()
1581           << "\");\n";
1582       out << "if (" << result_value << " != nullptr) {\n";
1583       out.indent();
1584       out << result_value << "->incStrong(" << result_value << ".get());\n";
1585       out << result_msg << "->set_hidl_interface_pointer("
1586           << "reinterpret_cast<uintptr_t>(" << result_value << ".get()));\n";
1587       out.unindent();
1588       out << "} else {\n";
1589       out.indent();
1590       out << result_msg << "->set_hidl_interface_pointer(0);\n";
1591       out.unindent();
1592       out << "}\n";
1593       break;
1594     }
1595     case TYPE_HIDL_MEMORY:
1596     {
1597       out << result_msg << "->set_type(TYPE_HIDL_MEMORY);\n";
1598       out << result_msg << "->mutable_hidl_memory_value()->set_hidl_mem_address"
1599           << "(reinterpret_cast<size_t>(new android::hardware::hidl_memory("
1600           << result_value << ")));\n";
1601       break;
1602     }
1603     case TYPE_POINTER:
1604     {
1605       out << result_msg << "->set_type(TYPE_POINTER);\n";
1606       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1607       break;
1608     }
1609     case TYPE_FMQ_SYNC:
1610     case TYPE_FMQ_UNSYNC:
1611     {
1612       out << result_msg << "->set_type("
1613           << (val.type() == TYPE_FMQ_SYNC ? "TYPE_FMQ_SYNC" : "TYPE_FMQ_UNSYNC")
1614           << ");\n";
1615       string item_name = result_msg + "_item";
1616       out << "VariableSpecificationMessage* " << item_name << " = "
1617           << result_msg << "->add_fmq_value();\n";
1618       if (val.fmq_value(0).type() == TYPE_SCALAR) {
1619         // This FMQ uses scalar type, stores type name in
1620         // scalar_type field.
1621         out << item_name << "->set_type(TYPE_SCALAR);\n";
1622         out << item_name << "->set_scalar_type(\""
1623             << val.fmq_value(0).scalar_type() << "\");\n";
1624       } else if (val.fmq_value(0).type() == TYPE_ENUM) {
1625         // This FMQ uses enum type, stores type name in
1626         // predefined_type field.
1627         out << item_name << "->set_type(TYPE_ENUM);\n";
1628         out << item_name << "->set_predefined_type(\""
1629             << val.fmq_value(0).predefined_type() << "\");\n";
1630       } else if (val.fmq_value(0).type() == TYPE_STRUCT) {
1631         // This FMQ uses struct type, stores type name in
1632         // predefined_type field.
1633         out << item_name << "->set_type(TYPE_STRUCT);\n";
1634         out << item_name << "->set_predefined_type(\""
1635             << val.fmq_value(0).predefined_type() << "\");\n";
1636       } else if (val.fmq_value(0).type() == TYPE_UNION) {
1637         // This FMQ uses union type, stores type name in
1638         // predefined_type field.
1639         out << item_name << "->set_type(TYPE_UNION);\n";
1640         out << item_name << "->set_predefined_type(\""
1641             << val.fmq_value(0).predefined_type() << "\");\n";
1642       } else {
1643         // FMQ doesn't support string, vector, or array type.
1644         out << "LOG(ERROR) << \"Unsupport type of data in FMQ\";\n";
1645       }
1646       // Cast result into address, and save it in proto.
1647       out << item_name << "->set_fmq_desc_address("
1648           << "reinterpret_cast<size_t>(new (std::nothrow) "
1649           << GetCppVariableType(val) << "(" << result_value << ")));\n";
1650       break;
1651     }
1652     case TYPE_REF:
1653     {
1654       out << result_msg << "->set_type(TYPE_REF);\n";
1655       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1656       break;
1657     }
1658     case TYPE_SAFE_UNION: {
1659       out << result_msg << "->set_type(TYPE_SAFE_UNION);\n";
1660       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
1661       break;
1662     }
1663     default:
1664     {
1665       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1666       exit(-1);
1667     }
1668   }
1669 }
1670 
GenerateSetResultDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1671 void HalHidlCodeGen::GenerateSetResultDeclForAttribute(Formatter& out,
1672     const VariableSpecificationMessage& attribute) {
1673   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
1674       attribute.type() == TYPE_SAFE_UNION) {
1675     // Recursively generate SetResult method implementation for all sub_types.
1676     for (const auto& sub_struct : attribute.sub_struct()) {
1677       GenerateSetResultDeclForAttribute(out, sub_struct);
1678     }
1679     for (const auto& sub_union : attribute.sub_union()) {
1680       GenerateSetResultDeclForAttribute(out, sub_union);
1681     }
1682     for (const auto& sub_safe_union : attribute.sub_safe_union()) {
1683       GenerateSetResultDeclForAttribute(out, sub_safe_union);
1684     }
1685   }
1686   // Add extern C to allow resource_manager to dynamically load this function.
1687   out << "extern \"C\" ";
1688   string func_name = "void SetResult"
1689       + ClearStringWithNameSpaceAccess(attribute.name());
1690   out << func_name << "(VariableSpecificationMessage* result_msg, "
1691       << attribute.name() << " result_value);\n";
1692 }
1693 
GenerateSetResultImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1694 void HalHidlCodeGen::GenerateSetResultImplForAttribute(Formatter& out,
1695     const VariableSpecificationMessage& attribute) {
1696   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
1697       attribute.type() == TYPE_SAFE_UNION) {
1698     // Recursively generate SetResult method implementation for all sub_types.
1699     for (const auto& sub_struct : attribute.sub_struct()) {
1700       GenerateSetResultImplForAttribute(out, sub_struct);
1701     }
1702     for (const auto& sub_union : attribute.sub_union()) {
1703       GenerateSetResultImplForAttribute(out, sub_union);
1704     }
1705     for (const auto& sub_safe_union : attribute.sub_safe_union()) {
1706       GenerateSetResultImplForAttribute(out, sub_safe_union);
1707     }
1708   }
1709   // Add extern C to allow resource_manager to dynamically load this function.
1710   out << "extern \"C\" ";
1711   string func_name = "void SetResult"
1712       + ClearStringWithNameSpaceAccess(attribute.name());
1713   out << func_name << "(VariableSpecificationMessage* result_msg, "
1714       << attribute.name() << " result_value __attribute__((__unused__))){\n";
1715   out.indent();
1716   GenerateSetResultCodeForTypedVariable(out, attribute, "result_msg",
1717                                         "result_value");
1718   out.unindent();
1719   out << "}\n\n";
1720 }
1721 
GenerateDefaultReturnValForTypedVariable(Formatter & out,const VariableSpecificationMessage & val)1722 void HalHidlCodeGen::GenerateDefaultReturnValForTypedVariable(
1723     Formatter& out, const VariableSpecificationMessage& val) {
1724   switch (val.type()) {
1725     case TYPE_SCALAR: {
1726       out << "static_cast<" << GetCppVariableType(val.scalar_type()) << ">(0)";
1727       break;
1728     }
1729     case TYPE_MASK: {
1730       out << "static_cast<" << GetCppVariableType(val.scalar_type()) << ">("
1731           << val.predefined_type() << "())";
1732       break;
1733     }
1734     case TYPE_HIDL_CALLBACK:
1735     case TYPE_HIDL_INTERFACE:
1736     case TYPE_POINTER:
1737     case TYPE_REF: {
1738       out << "nullptr";
1739       break;
1740     }
1741     case TYPE_STRING:
1742     case TYPE_ENUM:
1743     case TYPE_VECTOR:
1744     case TYPE_ARRAY:
1745     case TYPE_STRUCT:
1746     case TYPE_UNION:
1747     case TYPE_SAFE_UNION:
1748     case TYPE_HANDLE:
1749     case TYPE_HIDL_MEMORY:
1750     case TYPE_FMQ_SYNC:
1751     case TYPE_FMQ_UNSYNC: {
1752       out << GetCppVariableType(val) << "()";
1753       break;
1754     }
1755     default: {
1756       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1757       exit(-1);
1758     }
1759   }
1760 }
1761 
GenerateAllFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1762 void HalHidlCodeGen::GenerateAllFunctionDeclForAttribute(Formatter& out,
1763     const VariableSpecificationMessage& attribute) {
1764   GenerateDriverDeclForAttribute(out, attribute);
1765   GenerateRandomFunctionDeclForAttribute(out, attribute);
1766   GenerateVerificationDeclForAttribute(out, attribute);
1767   GenerateSetResultDeclForAttribute(out, attribute);
1768 }
1769 
GenerateAllFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1770 void HalHidlCodeGen::GenerateAllFunctionImplForAttribute(Formatter& out,
1771     const VariableSpecificationMessage& attribute) {
1772   GenerateDriverImplForAttribute(out, attribute);
1773   GenerateRandomFunctionImplForAttribute(out, attribute);
1774   GenerateVerificationImplForAttribute(out, attribute);
1775   GenerateSetResultImplForAttribute(out, attribute);
1776 }
1777 
CanElideCallback(const FunctionSpecificationMessage & func_msg)1778 bool HalHidlCodeGen::CanElideCallback(
1779     const FunctionSpecificationMessage& func_msg) {
1780   // Can't elide callback for void or tuple-returning methods
1781   if (func_msg.return_type_hidl_size() != 1) {
1782     return false;
1783   }
1784   const VariableType& type = func_msg.return_type_hidl(0).type();
1785   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
1786     return false;
1787   }
1788   return IsElidableType(type);
1789 }
1790 
1791 }  // namespace vts
1792 }  // namespace android
1793