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