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 <fmq/MessageQueue.h>\n";
563   out << "#include <sys/stat.h>\n";
564   out << "#include <unistd.h>\n";
565 }
566 
GenerateAdditionalFuctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message,const string &)567 void HalHidlCodeGen::GenerateAdditionalFuctionDeclarations(Formatter& out,
568     const ComponentSpecificationMessage& message,
569     const string& /*fuzzer_extended_class_name*/) {
570   if (message.component_name() != "types") {
571     out << "bool GetService(bool get_stub, const char* service_name);"
572         << "\n\n";
573   }
574 }
575 
GeneratePublicFunctionDeclarations(Formatter & out,const ComponentSpecificationMessage &)576 void HalHidlCodeGen::GeneratePublicFunctionDeclarations(
577     Formatter& out, const ComponentSpecificationMessage& /*message*/) {
578   out << "uint64_t GetHidlInterfaceProxy() const {\n";
579   out.indent();
580   out << "return reinterpret_cast<uintptr_t>(" << kInstanceVariableName
581       << ".get());\n";
582   out.unindent();
583   out << "}\n";
584 }
585 
GeneratePrivateMemberDeclarations(Formatter & out,const ComponentSpecificationMessage & message)586 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
587     const ComponentSpecificationMessage& message) {
588   FQName fqname = GetFQName(message);
589   out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
590 }
591 
GenerateRandomFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)592 void HalHidlCodeGen::GenerateRandomFunctionDeclForAttribute(Formatter& out,
593     const VariableSpecificationMessage& attribute) {
594   if (attribute.type() == TYPE_ENUM) {
595     if (attribute.enum_value().enumerator_size() == 0) {
596       // empty enum without any actual enumerator.
597       return;
598     }
599     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
600     out << attribute.enum_value().scalar_type() << " "
601         << "Random" << attribute_name << "();\n";
602   }
603 }
604 
GenerateRandomFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)605 void HalHidlCodeGen::GenerateRandomFunctionImplForAttribute(Formatter& out,
606     const VariableSpecificationMessage& attribute) {
607   // Random value generator
608   if (attribute.type() == TYPE_ENUM) {
609     if (attribute.enum_value().enumerator_size() == 0) {
610       // empty enum without any actual enumerator.
611       return;
612     }
613     string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
614     out << attribute.enum_value().scalar_type() << " Random" << attribute_name
615         << "() {\n";
616     out.indent();
617     out << attribute.enum_value().scalar_type() << " choice = " << "("
618         << attribute.enum_value().scalar_type() << ") " << "rand() / "
619         << attribute.enum_value().enumerator().size() << ";" << "\n";
620     if (attribute.enum_value().scalar_type().find("u") != 0) {
621       out << "if (choice < 0) choice *= -1;" << "\n";
622     }
623     for (int index = 0; index < attribute.enum_value().enumerator().size();
624         index++) {
625       out << "if (choice == ";
626       out << "(" << attribute.enum_value().scalar_type() << ") ";
627       if (attribute.enum_value().scalar_type() == "int8_t") {
628         out << attribute.enum_value().scalar_value(index).int8_t();
629       } else if (attribute.enum_value().scalar_type() == "uint8_t") {
630         out << attribute.enum_value().scalar_value(index).uint8_t() << "U";
631       } else if (attribute.enum_value().scalar_type() == "int16_t") {
632         out << attribute.enum_value().scalar_value(index).int16_t();
633       } else if (attribute.enum_value().scalar_type() == "uint16_t") {
634         out << attribute.enum_value().scalar_value(index).uint16_t() << "U";
635       } else if (attribute.enum_value().scalar_type() == "int32_t") {
636         out << attribute.enum_value().scalar_value(index).int32_t() << "L";
637       } else if (attribute.enum_value().scalar_type() == "uint32_t") {
638         out << attribute.enum_value().scalar_value(index).uint32_t() << "UL";
639       } else if (attribute.enum_value().scalar_type() == "int64_t") {
640         if (attribute.enum_value().scalar_value(index).int64_t() == LLONG_MIN) {
641           out << "LLONG_MIN";
642         } else {
643           out << attribute.enum_value().scalar_value(index).int64_t() << "LL";
644         }
645       } else if (attribute.enum_value().scalar_type() == "uint64_t") {
646         out << attribute.enum_value().scalar_value(index).uint64_t() << "ULL";
647       } else {
648         cerr << __func__ << ":" << __LINE__ << " ERROR unsupported enum type "
649             << attribute.enum_value().scalar_type() << "\n";
650         exit(-1);
651       }
652       out << ") return static_cast<" << attribute.enum_value().scalar_type()
653           << ">(" << attribute.name()
654           << "::" << attribute.enum_value().enumerator(index) << ");\n";
655     }
656     out << "return static_cast<" << attribute.enum_value().scalar_type() << ">("
657         << attribute.name() << "::" << attribute.enum_value().enumerator(0)
658         << ");\n";
659     out.unindent();
660     out << "}" << "\n";
661   }
662 }
663 
GenerateDriverDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)664 void HalHidlCodeGen::GenerateDriverDeclForAttribute(Formatter& out,
665     const VariableSpecificationMessage& attribute) {
666   if (!IsUserDefinedType(attribute.type())) {
667     cerr << attribute.type() << " is not a user defined type\n";
668     exit(-1);
669   }
670   for (const auto& sub_struct : attribute.sub_struct()) {
671     GenerateDriverDeclForAttribute(out, sub_struct);
672   }
673   for (const auto& sub_union : attribute.sub_union()) {
674     GenerateDriverDeclForAttribute(out, sub_union);
675   }
676   for (const auto& sub_safe_union : attribute.sub_safe_union()) {
677     GenerateDriverDeclForAttribute(out, sub_safe_union);
678   }
679   string func_name =
680       "MessageTo" + ClearStringWithNameSpaceAccess(attribute.name());
681   // Add extern C to allow resource_manager to dynamically load this function.
682   out << "extern \"C\" ";
683   out << "void " << func_name
684       << "(const VariableSpecificationMessage& var_msg, " << attribute.name()
685       << "* arg, const string& callback_socket_name);\n";
686 }
687 
GenerateDriverImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)688 void HalHidlCodeGen::GenerateDriverImplForAttribute(Formatter& out,
689     const VariableSpecificationMessage& attribute) {
690   if (!IsUserDefinedType(attribute.type())) {
691     cerr << attribute.type() << " is not a user defined type\n";
692     exit(-1);
693   }
694   // Recursively generate driver implementation method for all sub_types.
695   for (const auto& sub_struct : attribute.sub_struct()) {
696     GenerateDriverImplForAttribute(out, sub_struct);
697   }
698   for (const auto& sub_union : attribute.sub_union()) {
699     GenerateDriverImplForAttribute(out, sub_union);
700   }
701   for (const auto& sub_safe_union : attribute.sub_safe_union()) {
702     GenerateDriverImplForAttribute(out, sub_safe_union);
703   }
704   string func_name =
705       "MessageTo" + ClearStringWithNameSpaceAccess(attribute.name());
706   // Add extern C to allow resource_manager to dynamically load this
707   // function.
708   out << "extern \"C\" ";
709   out << "void " << func_name
710       << "(const VariableSpecificationMessage& "
711          "var_msg __attribute__((__unused__)), "
712       << attribute.name() << "* arg __attribute__((__unused__)), "
713       << "const string& callback_socket_name __attribute__((__unused__))) {"
714       << "\n";
715   out.indent();
716 
717   switch (attribute.type()) {
718     case TYPE_ENUM: {
719       out << "*arg = (" << attribute.name() << ")var_msg.scalar_value()."
720           << attribute.enum_value().scalar_type() << "();\n";
721       break;
722     }
723     case TYPE_STRUCT: {
724       int struct_index = 0;
725       for (const auto& struct_value : attribute.struct_value()) {
726         GenerateDriverImplForTypedVariable(
727             out, struct_value, "arg->" + struct_value.name(),
728             "var_msg.struct_value(" + std::to_string(struct_index) + ")");
729         struct_index++;
730       }
731       break;
732     }
733     case TYPE_UNION: {
734       int union_index = 0;
735       for (const auto& union_value : attribute.union_value()) {
736         out << "if (var_msg.union_value(" << union_index << ").name() == \""
737             << union_value.name() << "\") {"
738             << "\n";
739         out.indent();
740         GenerateDriverImplForTypedVariable(
741             out, union_value, "arg->" + union_value.name(),
742             "var_msg.union_value(" + std::to_string(union_index) + ")");
743         union_index++;
744         out.unindent();
745         out << "}\n";
746       }
747       break;
748     }
749     case TYPE_SAFE_UNION: {
750       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
751       break;
752     }
753     default: {
754       cerr << __func__ << " unsupported attribute type " << attribute.type()
755            << "\n";
756       exit(-1);
757     }
758   }
759   out.unindent();
760   out << "}\n";
761 }
762 
GenerateGetServiceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)763 void HalHidlCodeGen::GenerateGetServiceImpl(Formatter& out,
764     const ComponentSpecificationMessage& message,
765     const string& fuzzer_extended_class_name) {
766   out << "bool " << fuzzer_extended_class_name
767       << "::GetService(bool get_stub, const char* service_name) {" << "\n";
768   out.indent();
769   out << "static bool initialized = false;" << "\n";
770   out << "if (!initialized) {" << "\n";
771   out.indent();
772   out << "LOG(INFO) << \"HIDL getService\";"
773       << "\n";
774   out << "if (service_name) {\n"
775       << "  LOG(INFO) << \"  - service name: \" << service_name;"
776       << "\n"
777       << "}\n";
778   FQName fqname = GetFQName(message);
779   out << kInstanceVariableName << " = " << fqname.cppName() << "::getService("
780       << "service_name, get_stub);" << "\n";
781   out << "if (" << kInstanceVariableName << " == nullptr) {\n";
782   out.indent();
783   out << "LOG(ERROR) << \"getService() returned a null pointer.\";\n";
784   out << "return false;\n";
785   out.unindent();
786   out << "}\n";
787   out << "LOG(DEBUG) << \"" << kInstanceVariableName << " = \" << "
788       << kInstanceVariableName << ".get();"
789       << "\n";
790   out << "initialized = true;" << "\n";
791   out.unindent();
792   out << "}" << "\n";
793   out << "return true;" << "\n";
794   out.unindent();
795   out << "}" << "\n" << "\n";
796 }
797 
GenerateDriverImplForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & arg_name,const string & arg_value_name)798 void HalHidlCodeGen::GenerateDriverImplForTypedVariable(Formatter& out,
799     const VariableSpecificationMessage& val, const string& arg_name,
800     const string& arg_value_name) {
801   switch (val.type()) {
802     case TYPE_SCALAR:
803     {
804       out << arg_name << " = " << arg_value_name << ".scalar_value()."
805           << val.scalar_type() << "();\n";
806       break;
807     }
808     case TYPE_STRING:
809     {
810       out << arg_name << " = ::android::hardware::hidl_string("
811           << arg_value_name << ".string_value().message());\n";
812       break;
813     }
814     case TYPE_ENUM:
815     {
816       if (val.has_predefined_type()) {
817         string func_name =
818             "MessageTo" + ClearStringWithNameSpaceAccess(val.predefined_type());
819         out << func_name << "(" << arg_value_name << ", &(" << arg_name
820             << "), callback_socket_name);\n";
821       } else {
822         out << arg_name << " = (" << val.name() << ")" << arg_value_name << "."
823             << "enum_value().scalar_value(0)." << val.enum_value().scalar_type()
824             << "();\n";
825       }
826       break;
827     }
828     case TYPE_MASK:
829     {
830       out << arg_name << " = " << arg_value_name << ".scalar_value()."
831           << val.scalar_type() << "();\n";
832       break;
833     }
834     case TYPE_VECTOR:
835     {
836       out << arg_name << ".resize(" << arg_value_name
837           << ".vector_value_size());\n";
838       std::string index_name = GetVarString(arg_name) + "_index";
839       out << "for (int " << index_name << " = 0; " << index_name << " < "
840           << arg_value_name << ".vector_value_size(); " << index_name
841           << "++) {\n";
842       out.indent();
843       GenerateDriverImplForTypedVariable(
844           out, val.vector_value(0), arg_name + "[" + index_name + "]",
845           arg_value_name + ".vector_value(" + index_name + ")");
846       out.unindent();
847       out << "}\n";
848       break;
849     }
850     case TYPE_ARRAY:
851     {
852       std::string index_name = GetVarString(arg_name) + "_index";
853       out << "for (int " << index_name << " = 0; " << index_name << " < "
854           << arg_value_name << ".vector_value_size(); " << index_name
855           << "++) {\n";
856       out.indent();
857       GenerateDriverImplForTypedVariable(
858           out, val.vector_value(0), arg_name + "[" + index_name + "]",
859           arg_value_name + ".vector_value(" + index_name + ")");
860       out.unindent();
861       out << "}\n";
862       break;
863     }
864     case TYPE_STRUCT:
865     {
866       if (val.has_predefined_type()) {
867         string func_name = "MessageTo"
868             + ClearStringWithNameSpaceAccess(val.predefined_type());
869         out << func_name << "(" << arg_value_name << ", &(" << arg_name
870             << "), callback_socket_name);\n";
871       } else {
872         int struct_index = 0;
873         for (const auto& struct_field : val.struct_value()) {
874           string struct_field_name = arg_name + "." + struct_field.name();
875           string struct_field_value_name = arg_value_name + ".struct_value("
876               + std::to_string(struct_index) + ")";
877           GenerateDriverImplForTypedVariable(out, struct_field,
878                                              struct_field_name,
879                                              struct_field_value_name);
880           struct_index++;
881         }
882       }
883       break;
884     }
885     case TYPE_UNION:
886     {
887       if (val.has_predefined_type()) {
888         string func_name = "MessageTo"
889             + ClearStringWithNameSpaceAccess(val.predefined_type());
890         out << func_name << "(" << arg_value_name << ", &(" << arg_name
891             << "), callback_socket_name);\n";
892       } else {
893         int union_index = 0;
894         for (const auto& union_field : val.union_value()) {
895           string union_field_name = arg_name + "." + union_field.name();
896           string union_field_value_name = arg_value_name + ".union_value("
897               + std::to_string(union_index) + ")";
898           GenerateDriverImplForTypedVariable(out, union_field, union_field_name,
899                                              union_field_value_name);
900           union_index++;
901         }
902       }
903       break;
904     }
905     case TYPE_HIDL_CALLBACK:
906     {
907       string type_name = val.predefined_type();
908       ReplaceSubString(type_name, "::", "_");
909 
910       out << arg_name << " = VtsFuzzerCreateVts" << type_name
911           << "(callback_socket_name);\n";
912       out << "static_cast<" << "Vts" + type_name << "*>(" << arg_name
913           << ".get())->Register(" << arg_value_name << ");\n";
914       break;
915     }
916     case TYPE_HANDLE:
917     {
918       out << "if (" << arg_value_name << ".has_handle_value()) {\n";
919       out.indent();
920       out << "if (" << arg_value_name
921           << ".handle_value().has_hidl_handle_address()) {\n";
922       out.indent();  // if case starts: existing hidl_handle is specified.
923       out << arg_name
924           << " = *(reinterpret_cast<android::hardware::hidl_handle*>("
925           << arg_value_name << ".handle_value().hidl_handle_address()));\n";
926       out.unindent();  // if case ends.
927       out << "} else {\n";
928       out.indent();  // else case starts: create a new handle object.
929       out << "native_handle_t* handle = native_handle_create(" << arg_value_name
930           << ".handle_value().num_fds(), " << arg_value_name
931           << ".handle_value().num_ints());\n";
932       out << "if (!handle) {\n";
933       out.indent();
934       out << "LOG(ERROR) << \"Failed to create handle. \";\n";
935       out << "exit(-1);\n";
936       out.unindent();
937       out << "}\n";
938       out << "for (int fd_index = 0; fd_index < " << arg_value_name
939           << ".handle_value().num_fds() + " << arg_value_name
940           << ".handle_value().num_ints(); fd_index++) {\n";
941       out.indent();
942       out << "if (fd_index < " << arg_value_name
943           << ".handle_value().num_fds()) {\n";
944       out.indent();
945       out << "FdMessage fd_val = " << arg_value_name
946           << ".handle_value().fd_val(fd_index);\n";
947       out << "string file_name = fd_val.file_name();\n";
948       out << "switch (fd_val.type()) {\n";
949       out.indent();
950       out << "case FdType::FILE_TYPE:\n";
951       out << "{\n";
952       out.indent();
953       // Create the parent path recursively if not exist.
954       out << "size_t pre = 0; size_t pos = 0;\n";
955       out << "string dir;\n";
956       out << "struct stat st;\n";
957       out << "while((pos=file_name.find_first_of('/', pre)) "
958           << "!= string::npos){\n";
959       out.indent();
960       out << "dir = file_name.substr(0, pos++);\n";
961       out << "pre = pos;\n";
962       out << "if(dir.size() == 0) continue; // ignore leading /\n";
963       out << "if (stat(dir.c_str(), &st) == -1) {\n";
964       out << "LOG(INFO) << \" Creating dir: \" << dir;\n";
965       out.indent();
966       out << "mkdir(dir.c_str(), 0700);\n";
967       out.unindent();
968       out << "}\n";
969       out.unindent();
970       out << "}\n";
971       out << "int fd = open(file_name.c_str(), "
972           << "fd_val.flags() | O_CREAT, fd_val.mode());\n";
973       out << "if (fd == -1) {\n";
974       out.indent();
975       out << "LOG(ERROR) << \"Failed to open file: \" << file_name << \" "
976              "error: \" << errno;\n";
977       out << "exit (-1);\n";
978       out.unindent();
979       out << "}\n";
980       out << "handle->data[fd_index] = fd;\n";
981       out << "break;\n";
982       out.unindent();
983       out << "}\n";
984       out << "case FdType::DIR_TYPE:\n";
985       out << "{\n";
986       out.indent();
987       out << "struct stat st;\n";
988       out << "if (!stat(file_name.c_str(), &st)) {\n";
989       out.indent();
990       out << "mkdir(file_name.c_str(), fd_val.mode());\n";
991       out.unindent();
992       out << "}\n";
993       out << "handle->data[fd_index] = open(file_name.c_str(), O_DIRECTORY, "
994           << "fd_val.mode());\n";
995       out << "break;\n";
996       out.unindent();
997       out << "}\n";
998       out << "case FdType::DEV_TYPE:\n";
999       out << "{\n";
1000       out.indent();
1001       out << "if(file_name == \"/dev/ashmem\") {\n";
1002       out.indent();
1003       out << "handle->data[fd_index] = ashmem_create_region(\"SharedMemory\", "
1004           << "fd_val.memory().size());\n";
1005       out.unindent();
1006       out << "}\n";
1007       out << "break;\n";
1008       out.unindent();
1009       out << "}\n";
1010       out << "case FdType::PIPE_TYPE:\n";
1011       out << "case FdType::SOCKET_TYPE:\n";
1012       out << "case FdType::LINK_TYPE:\n";
1013       out << "{\n";
1014       out.indent();
1015       out << "LOG(ERROR) << \"Not supported yet. \";\n";
1016       out << "break;\n";
1017       out.unindent();
1018       out << "}\n";
1019       out.unindent();
1020       out << "}\n";
1021       out.unindent();
1022       out << "} else {\n";
1023       out.indent();
1024       out << "handle->data[fd_index] = " << arg_value_name
1025           << ".handle_value().int_val(fd_index -" << arg_value_name
1026           << ".handle_value().num_fds());\n";
1027       out.unindent();
1028       out << "}\n";
1029       out.unindent();
1030       out << "}\n";
1031       out << arg_name << " = handle;\n";
1032       out.unindent();  // else case (create a new handle object) ends.
1033       out << "}\n";
1034       out.unindent();
1035       out << "} else {\n";
1036       out.indent();
1037       out << arg_name << " = nullptr;\n";
1038       out.unindent();
1039       out << "}\n";
1040       break;
1041     }
1042     case TYPE_HIDL_INTERFACE:
1043     {
1044       string type_name = val.predefined_type();
1045       out << "if (" << arg_value_name << ".has_hidl_interface_pointer()) {\n";
1046       out.indent();
1047       out << arg_name << " = reinterpret_cast<" << type_name << "*>("
1048           << arg_value_name << ".hidl_interface_pointer());\n";
1049       out.unindent();
1050       out << "} else {\n";
1051       out.indent();
1052       if (type_name.find("::android::hidl") == 0) {
1053         out << "LOG(ERROR) << \"general interface is not supported yet. \";\n";
1054       } else {
1055         ReplaceSubString(type_name, "::", "_");
1056         out << arg_name << " = VtsFuzzerCreateVts" << type_name
1057             << "(callback_socket_name);\n";
1058       }
1059       out.unindent();
1060       out << "}\n";
1061       break;
1062     }
1063     case TYPE_HIDL_MEMORY:
1064     {
1065       out << "if (" << arg_value_name
1066           << ".hidl_memory_value().has_hidl_mem_address()) {\n";
1067       out.indent();  // if case starts: existing hidl_memory is used.
1068       out << arg_name
1069           << " = *(reinterpret_cast<android::hardware::hidl_memory*>("
1070           << arg_value_name << ".hidl_memory_value().hidl_mem_address()));\n";
1071       out.unindent();  // if case ends.
1072       out << "} else {\n";
1073       out.indent();  // else case starts: allocates new memory region.
1074       out << "sp<::android::hidl::allocator::V1_0::IAllocator> ashmemAllocator"
1075           << " = ::android::hidl::allocator::V1_0::IAllocator::getService(\""
1076           << "ashmem\");\n";
1077       out << "if (ashmemAllocator == nullptr) {\n";
1078       out.indent();
1079       out << "LOG(ERROR) << \"Failed to get ashmemAllocator! \";\n";
1080       out << "exit(-1);\n";
1081       out.unindent();
1082       out << "}\n";
1083       // TODO(zhuoyao): initialize memory with recorded contents.
1084       out << "auto res = ashmemAllocator->allocate(" << arg_value_name
1085           << ".hidl_memory_value().size(), [&](bool success, "
1086           << "const hardware::hidl_memory& memory) {\n";
1087       out.indent();
1088       out << "if (!success) {\n";
1089       out.indent();
1090       out << "LOG(ERROR) << \"Failed to allocate memory! \";\n";
1091       out << arg_name << " = ::android::hardware::hidl_memory();\n";
1092       out << "return;\n";
1093       out.unindent();
1094       out << "}\n";
1095       out << arg_name << " = memory;\n";
1096       out.unindent();
1097       out << "});\n";
1098       out.unindent();  // else case ends.
1099       out << "}\n";
1100       break;
1101     }
1102     case TYPE_POINTER:
1103     {
1104       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1105       break;
1106     }
1107     case TYPE_FMQ_SYNC:
1108     case TYPE_FMQ_UNSYNC: {
1109       if (arg_name.find("->") != std::string::npos) {
1110         out << "LOG(ERROR) << \"Nested structure with fmq is not supported "
1111                "yet. \";\n";
1112       } else {
1113         // TODO(zhuoyao): consider record and use the queue capacity.
1114         std::string element_type = GetCppVariableType(val.fmq_value(0));
1115         std::string queue_name =
1116             arg_name + (val.type() == TYPE_FMQ_SYNC ? "_sync_q" : "_unsync_q");
1117         std::string queue_descriptor_type = GetCppVariableType(val);
1118 
1119         // When caller wants to reuse an existing queue.
1120         out << "if (" << arg_value_name << ".fmq_value_size() > 0 && "
1121             << arg_value_name << ".fmq_value(0).has_fmq_desc_address()) {\n";
1122         out.indent();  // if case starts
1123         out << arg_name << " = "
1124             << "reinterpret_cast<" << queue_descriptor_type << "*>("
1125             << arg_value_name << ".fmq_value(0).fmq_desc_address());\n";
1126         out.unindent();  // if case ends
1127 
1128         // When caller wants to create a brand new queue and write to it.
1129         out << "} else {\n";
1130         out.indent();  // else case starts
1131         out << "::android::hardware::MessageQueue<" << element_type
1132             << ", ::android::hardware::"
1133             << (val.type() == TYPE_FMQ_SYNC ? "kSynchronizedReadWrite"
1134                                             : "kUnsynchronizedWrite")
1135             << "> " << queue_name << "(1024);\n";
1136         out << "for (int i = 0; i < (int)" << arg_value_name
1137             << ".fmq_value_size(); i++) {\n";
1138         out.indent();  // for loop starts
1139         std::string fmq_item_name = queue_name + "_item";
1140         out << element_type << " " << fmq_item_name << ";\n";
1141         GenerateDriverImplForTypedVariable(out, val.fmq_value(0), fmq_item_name,
1142                                            arg_value_name + ".fmq_value(i)");
1143         out << queue_name << ".write(&" << fmq_item_name << ");\n";
1144         out.unindent();  // for loop ends
1145         out << "}\n";
1146         out << arg_name << " = " << queue_name << ".getDesc();\n";
1147         out.unindent();  // else case ends
1148         out << "}\n";
1149       }
1150       break;
1151     }
1152     case TYPE_REF:
1153     {
1154       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1155       break;
1156     }
1157     case TYPE_SAFE_UNION: {
1158       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
1159       break;
1160     }
1161     default:
1162     {
1163       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1164       exit(-1);
1165     }
1166   }
1167 }
1168 
1169 // TODO(zhuoyao): Verify results based on verification rules instead of perform
1170 // an exact match.
GenerateVerificationFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)1171 void HalHidlCodeGen::GenerateVerificationFunctionImpl(Formatter& out,
1172     const ComponentSpecificationMessage& message,
1173     const string& fuzzer_extended_class_name) {
1174   if (message.component_name() != "types") {
1175     // Generate the main profiler function.
1176     out << "\nbool " << fuzzer_extended_class_name;
1177     out.indent();
1178     out << "::VerifyResults(const FunctionSpecificationMessage& "
1179            "expected_result __attribute__((__unused__)),"
1180         << "\n";
1181     out << "const FunctionSpecificationMessage& actual_result "
1182            "__attribute__((__unused__))) {\n";
1183     for (const FunctionSpecificationMessage& api : message.interface().api()) {
1184       out << "if (!strcmp(actual_result.name().c_str(), \"" << api.name()
1185           << "\")) {\n";
1186       out.indent();
1187       out << "if (actual_result.return_type_hidl_size() != "
1188           << "expected_result.return_type_hidl_size() "
1189           << ") { return false; }\n";
1190       for (int i = 0; i < api.return_type_hidl_size(); i++) {
1191         std::string expected_result = "expected_result.return_type_hidl("
1192             + std::to_string(i) + ")";
1193         std::string actual_result = "actual_result.return_type_hidl("
1194             + std::to_string(i) + ")";
1195         GenerateVerificationCodeForTypedVariable(out, api.return_type_hidl(i),
1196                                                  expected_result,
1197                                                  actual_result);
1198       }
1199       out << "return true;\n";
1200       out.unindent();
1201       out << "}\n";
1202     }
1203     out << "return false;\n";
1204     out.unindent();
1205     out << "}\n\n";
1206   }
1207 }
1208 
GenerateVerificationCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & expected_result,const string & actual_result)1209 void HalHidlCodeGen::GenerateVerificationCodeForTypedVariable(Formatter& out,
1210     const VariableSpecificationMessage& val, const string& expected_result,
1211     const string& actual_result) {
1212   switch (val.type()) {
1213     case TYPE_SCALAR:
1214     {
1215       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
1216           << "() != " << expected_result << ".scalar_value()."
1217           << val.scalar_type() << "()) { return false; }\n";
1218       break;
1219     }
1220     case TYPE_STRING:
1221     {
1222       out << "if (strcmp(" << actual_result
1223           << ".string_value().message().c_str(), " << expected_result
1224           << ".string_value().message().c_str())!= 0)" << "{ return false; }\n";
1225       break;
1226     }
1227     case TYPE_ENUM:
1228     {
1229       if (val.has_predefined_type()) {
1230         string func_name = "Verify"
1231             + ClearStringWithNameSpaceAccess(val.predefined_type());
1232         out << "if(!" << func_name << "(" << expected_result << ", "
1233             << actual_result << ")) { return false; }\n";
1234       } else {
1235         out << "if (" << actual_result << ".scalar_value()."
1236             << val.enum_value().scalar_type() << "() != " << expected_result
1237             << ".scalar_value()." << val.enum_value().scalar_type()
1238             << "()) { return false; }\n";
1239       }
1240       break;
1241     }
1242     case TYPE_MASK:
1243     {
1244       out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
1245           << "() != " << expected_result << ".scalar_value()."
1246           << val.scalar_type() << "()) { return false; }\n";
1247       break;
1248     }
1249     case TYPE_VECTOR:
1250     {
1251       out << "if (" << actual_result << ".vector_value_size() != "
1252           << expected_result << ".vector_value_size()) {\n";
1253       out.indent();
1254       out << "LOG(ERROR) << \"Verification failed for vector size. expected: "
1255              "\" << "
1256           << expected_result << ".vector_value_size() << \" actual: \" << "
1257           << actual_result << ".vector_value_size();\n";
1258       out << "return false;\n";
1259       out.unindent();
1260       out << "}\n";
1261       out << "for (int i = 0; i <" << expected_result
1262           << ".vector_value_size(); i++) {\n";
1263       out.indent();
1264       GenerateVerificationCodeForTypedVariable(
1265           out, val.vector_value(0), expected_result + ".vector_value(i)",
1266           actual_result + ".vector_value(i)");
1267       out.unindent();
1268       out << "}\n";
1269       break;
1270     }
1271     case TYPE_ARRAY:
1272     {
1273       out << "if (" << actual_result << ".vector_value_size() != "
1274           << expected_result << ".vector_value_size()) {\n";
1275       out.indent();
1276       out << "LOG(ERROR) << \"Verification failed for vector size. expected: "
1277              "\" << "
1278           << expected_result << ".vector_value_size() << \" actual: \" << "
1279           << actual_result << ".vector_value_size();\n";
1280       out << "return false;\n";
1281       out.unindent();
1282       out << "}\n";
1283       out << "for (int i = 0; i < " << expected_result
1284           << ".vector_value_size(); i++) {\n";
1285       out.indent();
1286       GenerateVerificationCodeForTypedVariable(
1287           out, val.vector_value(0), expected_result + ".vector_value(i)",
1288           actual_result + ".vector_value(i)");
1289       out.unindent();
1290       out << "}\n";
1291       break;
1292     }
1293     case TYPE_STRUCT:
1294     {
1295       if (val.has_predefined_type()) {
1296         string func_name = "Verify"
1297             + ClearStringWithNameSpaceAccess(val.predefined_type());
1298         out << "if (!" << func_name << "(" << expected_result << ", "
1299             << actual_result << ")) { return false; }\n";
1300       } else {
1301         for (int i = 0; i < val.struct_value_size(); i++) {
1302           string struct_field_actual_result = actual_result + ".struct_value("
1303               + std::to_string(i) + ")";
1304           string struct_field_expected_result = expected_result
1305               + ".struct_value(" + std::to_string(i) + ")";
1306           GenerateVerificationCodeForTypedVariable(out, val.struct_value(i),
1307                                                    struct_field_expected_result,
1308                                                    struct_field_actual_result);
1309         }
1310       }
1311       break;
1312     }
1313     case TYPE_UNION:
1314     {
1315       if (val.has_predefined_type()) {
1316         string func_name = "Verify"
1317             + ClearStringWithNameSpaceAccess(val.predefined_type());
1318         out << "if (!" << func_name << "(" << expected_result << ", "
1319             << actual_result << ")) {return false; }\n";
1320       } else {
1321         for (int i = 0; i < val.union_value_size(); i++) {
1322           string union_field_actual_result = actual_result + ".union_value("
1323               + std::to_string(i) + ")";
1324           string union_field_expected_result = expected_result + ".union_value("
1325               + std::to_string(i) + ")";
1326           GenerateVerificationCodeForTypedVariable(out, val.union_value(i),
1327                                                    union_field_expected_result,
1328                                                    union_field_actual_result);
1329         }
1330       }
1331       break;
1332     }
1333     case TYPE_HIDL_CALLBACK:
1334     {
1335       out << "LOG(ERROR) << \"TYPE_HILD_CALLBACK is not supported yet. \";\n";
1336       break;
1337     }
1338     case TYPE_HANDLE:
1339     {
1340       out << "LOG(ERROR) << \"TYPE_HANDLE is not supported yet. \";\n";
1341       break;
1342     }
1343     case TYPE_HIDL_INTERFACE:
1344     {
1345       out << "LOG(ERROR) << \"TYPE_HIDL_INTERFACE is not supported yet. \";\n";
1346       break;
1347     }
1348     case TYPE_HIDL_MEMORY:
1349     {
1350       out << "LOG(ERROR) << \"TYPE_HIDL_MEMORY is not supported yet. \";\n";
1351       break;
1352     }
1353     case TYPE_POINTER:
1354     {
1355       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1356       break;
1357     }
1358     case TYPE_FMQ_SYNC:
1359     {
1360       out << "LOG(ERROR) << \"TYPE_FMQ_SYNC is not supported yet. \";\n";
1361       break;
1362     }
1363     case TYPE_FMQ_UNSYNC:
1364     {
1365       out << "LOG(ERROR) << \"TYPE_FMQ_UNSYNC is not supported yet. \";\n";
1366       break;
1367     }
1368     case TYPE_REF:
1369     {
1370       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1371       break;
1372     }
1373     case TYPE_SAFE_UNION: {
1374       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is Not supported yet. \";\n";
1375       break;
1376     }
1377     default:
1378     {
1379       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1380       exit(-1);
1381     }
1382   }
1383 }
1384 
GenerateVerificationDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1385 void HalHidlCodeGen::GenerateVerificationDeclForAttribute(Formatter& out,
1386     const VariableSpecificationMessage& attribute) {
1387   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1388     // Recursively generate verification method implementation for all sub_types.
1389     for (const auto& sub_struct : attribute.sub_struct()) {
1390       GenerateVerificationDeclForAttribute(out, sub_struct);
1391     }
1392     for (const auto& sub_union : attribute.sub_union()) {
1393       GenerateVerificationDeclForAttribute(out, sub_union);
1394     }
1395   }
1396   std::string func_name = "bool Verify"
1397       + ClearStringWithNameSpaceAccess(attribute.name());
1398   out << func_name << "(const VariableSpecificationMessage& expected_result, "
1399       << "const VariableSpecificationMessage& actual_result);\n";
1400 }
1401 
GenerateVerificationImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1402 void HalHidlCodeGen::GenerateVerificationImplForAttribute(Formatter& out,
1403     const VariableSpecificationMessage& attribute) {
1404   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1405     // Recursively generate verification method implementation for all sub_types.
1406     for (const auto& sub_struct : attribute.sub_struct()) {
1407       GenerateVerificationImplForAttribute(out, sub_struct);
1408     }
1409     for (const auto& sub_union : attribute.sub_union()) {
1410       GenerateVerificationImplForAttribute(out, sub_union);
1411     }
1412   }
1413   std::string func_name = "bool Verify"
1414       + ClearStringWithNameSpaceAccess(attribute.name());
1415   out << func_name << "(const VariableSpecificationMessage& expected_result "
1416                       "__attribute__((__unused__)), "
1417       << "const VariableSpecificationMessage& actual_result "
1418          "__attribute__((__unused__))){\n";
1419   out.indent();
1420   GenerateVerificationCodeForTypedVariable(out, attribute, "expected_result",
1421                                            "actual_result");
1422   out << "return true;\n";
1423   out.unindent();
1424   out << "}\n\n";
1425 }
1426 
1427 // TODO(zhuoyao): consider to generalize the pattern for
1428 // Verification/SetResult/DriverImpl.
GenerateSetResultCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & result_msg,const string & result_value)1429 void HalHidlCodeGen::GenerateSetResultCodeForTypedVariable(Formatter& out,
1430     const VariableSpecificationMessage& val, const string& result_msg,
1431     const string& result_value) {
1432   switch (val.type()) {
1433     case TYPE_SCALAR:
1434     {
1435       out << result_msg << "->set_type(TYPE_SCALAR);\n";
1436       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1437           << "\");\n";
1438       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1439           << "(" << result_value << ");\n";
1440       break;
1441     }
1442     case TYPE_STRING:
1443     {
1444       out << result_msg << "->set_type(TYPE_STRING);\n";
1445       out << result_msg << "->mutable_string_value()->set_message" << "("
1446           << result_value << ".c_str());\n";
1447       out << result_msg << "->mutable_string_value()->set_length" << "("
1448           << result_value << ".size());\n";
1449       break;
1450     }
1451     case TYPE_ENUM:
1452     {
1453       out << result_msg << "->set_type(TYPE_ENUM);\n";
1454       if (val.has_predefined_type()) {
1455         string func_name = "SetResult"
1456             + ClearStringWithNameSpaceAccess(val.predefined_type());
1457         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1458       } else {
1459         const string scalar_type = val.enum_value().scalar_type();
1460         out << result_msg << "->set_scalar_type(\"" << scalar_type << "\");\n";
1461         out << result_msg << "->mutable_scalar_value()->set_" << scalar_type
1462             << "(static_cast<" << scalar_type << ">(" << result_value
1463             << "));\n";
1464       }
1465       break;
1466     }
1467     case TYPE_MASK:
1468     {
1469       out << result_msg << "->set_type(TYPE_MASK);\n";
1470       out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1471           << "\");\n";
1472       out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1473           << "(" << result_value << ");\n";
1474       break;
1475     }
1476     case TYPE_VECTOR:
1477     {
1478       out << result_msg << "->set_type(TYPE_VECTOR);\n";
1479       out << result_msg << "->set_vector_size(" << result_value
1480           << ".size());\n";
1481       out << "for (int i = 0; i < (int)" << result_value << ".size(); i++) {\n";
1482       out.indent();
1483       string vector_element_name = result_msg + "_vector_i";
1484       out << "auto *" << vector_element_name << " = " << result_msg
1485           << "->add_vector_value();\n";
1486       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1487                                             vector_element_name,
1488                                             result_value + "[i]");
1489       out.unindent();
1490       out << "}\n";
1491       break;
1492     }
1493     case TYPE_ARRAY:
1494     {
1495       out << result_msg << "->set_type(TYPE_ARRAY);\n";
1496       out << result_msg << "->set_vector_size(" << val.vector_value_size()
1497           << ");\n";
1498       out << "for (int i = 0; i < " << val.vector_value_size() << "; i++) {\n";
1499       out.indent();
1500       string array_element_name = result_msg + "_array_i";
1501       out << "auto *" << array_element_name << " = " << result_msg
1502           << "->add_vector_value();\n";
1503       GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1504                                             array_element_name,
1505                                             result_value + "[i]");
1506       out.unindent();
1507       out << "}\n";
1508       break;
1509     }
1510     case TYPE_STRUCT:
1511     {
1512       out << result_msg << "->set_type(TYPE_STRUCT);\n";
1513       if (val.has_predefined_type()) {
1514         string func_name = "SetResult"
1515             + ClearStringWithNameSpaceAccess(val.predefined_type());
1516         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1517       } else {
1518         for (const auto& struct_field : val.struct_value()) {
1519           string struct_field_name = result_msg + "_" + struct_field.name();
1520           out << "auto *" << struct_field_name << " = " << result_msg
1521               << "->add_struct_value();\n";
1522           GenerateSetResultCodeForTypedVariable(
1523               out, struct_field, struct_field_name,
1524               result_value + "." + struct_field.name());
1525           if (struct_field.has_name()) {
1526             out << struct_field_name << "->set_name(\""
1527                 << struct_field.name() << "\");\n";
1528           }
1529         }
1530       }
1531       break;
1532     }
1533     case TYPE_UNION:
1534     {
1535       out << result_msg << "->set_type(TYPE_UNION);\n";
1536       if (val.has_predefined_type()) {
1537         string func_name = "SetResult"
1538             + ClearStringWithNameSpaceAccess(val.predefined_type());
1539         out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1540       } else {
1541         for (const auto& union_field : val.union_value()) {
1542           string union_field_name = result_msg + "_" + union_field.name();
1543           out << "auto *" << union_field_name << " = " << result_msg
1544               << "->add_union_value();\n";
1545           GenerateSetResultCodeForTypedVariable(
1546               out, union_field, union_field_name,
1547               result_value + "." + union_field.name());
1548           if (union_field.has_name()) {
1549             out << union_field_name << "->set_name(\"" << union_field.name()
1550                 << "\");\n";
1551           }
1552         }
1553       }
1554       break;
1555     }
1556     case TYPE_HIDL_CALLBACK:
1557     {
1558       out << result_msg << "->set_type(TYPE_HIDL_CALLBACK);\n";
1559       out << "LOG(ERROR) << \"TYPE HIDL_CALLBACK is not supported yet. \";\n";
1560       break;
1561     }
1562     case TYPE_HANDLE:
1563     {
1564       out << result_msg << "->set_type(TYPE_HANDLE);\n";
1565       out << result_msg << "->mutable_handle_value()->set_hidl_handle_address"
1566           << "(reinterpret_cast<size_t>(new android::hardware::hidl_handle("
1567           << result_value << ")));\n";
1568       break;
1569     }
1570     case TYPE_HIDL_INTERFACE:
1571     {
1572       out << result_msg << "->set_type(TYPE_HIDL_INTERFACE);\n";
1573       if (!val.has_predefined_type()) {
1574         cerr << __func__ << ":" << __LINE__
1575              << " HIDL interface is a return type"
1576              << "but predefined_type is unset." << endl;
1577         exit(-1);
1578       }
1579       out << result_msg << "->set_predefined_type(\"" << val.predefined_type()
1580           << "\");\n";
1581       out << "if (" << result_value << " != nullptr) {\n";
1582       out.indent();
1583       out << result_value << "->incStrong(" << result_value << ".get());\n";
1584       out << result_msg << "->set_hidl_interface_pointer("
1585           << "reinterpret_cast<uintptr_t>(" << result_value << ".get()));\n";
1586       out.unindent();
1587       out << "} else {\n";
1588       out.indent();
1589       out << result_msg << "->set_hidl_interface_pointer(0);\n";
1590       out.unindent();
1591       out << "}\n";
1592       break;
1593     }
1594     case TYPE_HIDL_MEMORY:
1595     {
1596       out << result_msg << "->set_type(TYPE_HIDL_MEMORY);\n";
1597       out << result_msg << "->mutable_hidl_memory_value()->set_hidl_mem_address"
1598           << "(reinterpret_cast<size_t>(new android::hardware::hidl_memory("
1599           << result_value << ")));\n";
1600       break;
1601     }
1602     case TYPE_POINTER:
1603     {
1604       out << result_msg << "->set_type(TYPE_POINTER);\n";
1605       out << "LOG(ERROR) << \"TYPE_POINTER is not supported yet. \";\n";
1606       break;
1607     }
1608     case TYPE_FMQ_SYNC:
1609     case TYPE_FMQ_UNSYNC:
1610     {
1611       out << result_msg << "->set_type("
1612           << (val.type() == TYPE_FMQ_SYNC ? "TYPE_FMQ_SYNC" : "TYPE_FMQ_UNSYNC")
1613           << ");\n";
1614       string item_name = result_msg + "_item";
1615       out << "VariableSpecificationMessage* " << item_name << " = "
1616           << result_msg << "->add_fmq_value();\n";
1617       if (val.fmq_value(0).type() == TYPE_SCALAR) {
1618         // This FMQ uses scalar type, stores type name in
1619         // scalar_type field.
1620         out << item_name << "->set_type(TYPE_SCALAR);\n";
1621         out << item_name << "->set_scalar_type(\""
1622             << val.fmq_value(0).scalar_type() << "\");\n";
1623       } else if (val.fmq_value(0).type() == TYPE_ENUM) {
1624         // This FMQ uses enum type, stores type name in
1625         // predefined_type field.
1626         out << item_name << "->set_type(TYPE_ENUM);\n";
1627         out << item_name << "->set_predefined_type(\""
1628             << val.fmq_value(0).predefined_type() << "\");\n";
1629       } else if (val.fmq_value(0).type() == TYPE_STRUCT) {
1630         // This FMQ uses struct type, stores type name in
1631         // predefined_type field.
1632         out << item_name << "->set_type(TYPE_STRUCT);\n";
1633         out << item_name << "->set_predefined_type(\""
1634             << val.fmq_value(0).predefined_type() << "\");\n";
1635       } else if (val.fmq_value(0).type() == TYPE_UNION) {
1636         // This FMQ uses union type, stores type name in
1637         // predefined_type field.
1638         out << item_name << "->set_type(TYPE_UNION);\n";
1639         out << item_name << "->set_predefined_type(\""
1640             << val.fmq_value(0).predefined_type() << "\");\n";
1641       } else {
1642         // FMQ doesn't support string, vector, or array type.
1643         out << "LOG(ERROR) << \"Unsupport type of data in FMQ\";\n";
1644       }
1645       // Cast result into address, and save it in proto.
1646       out << item_name << "->set_fmq_desc_address("
1647           << "reinterpret_cast<size_t>(new (std::nothrow) "
1648           << GetCppVariableType(val) << "(" << result_value << ")));\n";
1649       break;
1650     }
1651     case TYPE_REF:
1652     {
1653       out << result_msg << "->set_type(TYPE_REF);\n";
1654       out << "LOG(ERROR) << \"TYPE_REF is not supported yet. \";\n";
1655       break;
1656     }
1657     case TYPE_SAFE_UNION: {
1658       out << result_msg << "->set_type(TYPE_SAFE_UNION);\n";
1659       out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
1660       break;
1661     }
1662     default:
1663     {
1664       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1665       exit(-1);
1666     }
1667   }
1668 }
1669 
GenerateSetResultDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1670 void HalHidlCodeGen::GenerateSetResultDeclForAttribute(Formatter& out,
1671     const VariableSpecificationMessage& attribute) {
1672   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
1673       attribute.type() == TYPE_SAFE_UNION) {
1674     // Recursively generate SetResult method implementation for all sub_types.
1675     for (const auto& sub_struct : attribute.sub_struct()) {
1676       GenerateSetResultDeclForAttribute(out, sub_struct);
1677     }
1678     for (const auto& sub_union : attribute.sub_union()) {
1679       GenerateSetResultDeclForAttribute(out, sub_union);
1680     }
1681     for (const auto& sub_safe_union : attribute.sub_safe_union()) {
1682       GenerateSetResultDeclForAttribute(out, sub_safe_union);
1683     }
1684   }
1685   // Add extern C to allow resource_manager to dynamically load this function.
1686   out << "extern \"C\" ";
1687   string func_name = "void SetResult"
1688       + ClearStringWithNameSpaceAccess(attribute.name());
1689   out << func_name << "(VariableSpecificationMessage* result_msg, "
1690       << attribute.name() << " result_value);\n";
1691 }
1692 
GenerateSetResultImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1693 void HalHidlCodeGen::GenerateSetResultImplForAttribute(Formatter& out,
1694     const VariableSpecificationMessage& attribute) {
1695   if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
1696       attribute.type() == TYPE_SAFE_UNION) {
1697     // Recursively generate SetResult method implementation for all sub_types.
1698     for (const auto& sub_struct : attribute.sub_struct()) {
1699       GenerateSetResultImplForAttribute(out, sub_struct);
1700     }
1701     for (const auto& sub_union : attribute.sub_union()) {
1702       GenerateSetResultImplForAttribute(out, sub_union);
1703     }
1704     for (const auto& sub_safe_union : attribute.sub_safe_union()) {
1705       GenerateSetResultImplForAttribute(out, sub_safe_union);
1706     }
1707   }
1708   // Add extern C to allow resource_manager to dynamically load this function.
1709   out << "extern \"C\" ";
1710   string func_name = "void SetResult"
1711       + ClearStringWithNameSpaceAccess(attribute.name());
1712   out << func_name << "(VariableSpecificationMessage* result_msg, "
1713       << attribute.name() << " result_value __attribute__((__unused__))){\n";
1714   out.indent();
1715   GenerateSetResultCodeForTypedVariable(out, attribute, "result_msg",
1716                                         "result_value");
1717   out.unindent();
1718   out << "}\n\n";
1719 }
1720 
GenerateDefaultReturnValForTypedVariable(Formatter & out,const VariableSpecificationMessage & val)1721 void HalHidlCodeGen::GenerateDefaultReturnValForTypedVariable(
1722     Formatter& out, const VariableSpecificationMessage& val) {
1723   switch (val.type()) {
1724     case TYPE_SCALAR: {
1725       out << "static_cast<" << GetCppVariableType(val.scalar_type()) << ">(0)";
1726       break;
1727     }
1728     case TYPE_MASK: {
1729       out << "static_cast<" << GetCppVariableType(val.scalar_type()) << ">("
1730           << val.predefined_type() << "())";
1731       break;
1732     }
1733     case TYPE_HIDL_CALLBACK:
1734     case TYPE_HIDL_INTERFACE:
1735     case TYPE_POINTER:
1736     case TYPE_REF: {
1737       out << "nullptr";
1738       break;
1739     }
1740     case TYPE_STRING:
1741     case TYPE_ENUM:
1742     case TYPE_VECTOR:
1743     case TYPE_ARRAY:
1744     case TYPE_STRUCT:
1745     case TYPE_UNION:
1746     case TYPE_SAFE_UNION:
1747     case TYPE_HANDLE:
1748     case TYPE_HIDL_MEMORY:
1749     case TYPE_FMQ_SYNC:
1750     case TYPE_FMQ_UNSYNC: {
1751       out << GetCppVariableType(val) << "()";
1752       break;
1753     }
1754     default: {
1755       cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1756       exit(-1);
1757     }
1758   }
1759 }
1760 
GenerateAllFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1761 void HalHidlCodeGen::GenerateAllFunctionDeclForAttribute(Formatter& out,
1762     const VariableSpecificationMessage& attribute) {
1763   GenerateDriverDeclForAttribute(out, attribute);
1764   GenerateRandomFunctionDeclForAttribute(out, attribute);
1765   GenerateVerificationDeclForAttribute(out, attribute);
1766   GenerateSetResultDeclForAttribute(out, attribute);
1767 }
1768 
GenerateAllFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1769 void HalHidlCodeGen::GenerateAllFunctionImplForAttribute(Formatter& out,
1770     const VariableSpecificationMessage& attribute) {
1771   GenerateDriverImplForAttribute(out, attribute);
1772   GenerateRandomFunctionImplForAttribute(out, attribute);
1773   GenerateVerificationImplForAttribute(out, attribute);
1774   GenerateSetResultImplForAttribute(out, attribute);
1775 }
1776 
CanElideCallback(const FunctionSpecificationMessage & func_msg)1777 bool HalHidlCodeGen::CanElideCallback(
1778     const FunctionSpecificationMessage& func_msg) {
1779   // Can't elide callback for void or tuple-returning methods
1780   if (func_msg.return_type_hidl_size() != 1) {
1781     return false;
1782   }
1783   const VariableType& type = func_msg.return_type_hidl(0).type();
1784   if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
1785     return false;
1786   }
1787   return IsElidableType(type);
1788 }
1789 
1790 }  // namespace vts
1791 }  // namespace android
1792