1 /*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "code_gen/driver/HalHidlCodeGen.h"
18
19 #include <fstream>
20 #include <iostream>
21 #include <set>
22 #include <sstream>
23 #include <string>
24
25 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
26
27 #include "VtsCompilerUtils.h"
28 #include "utils/InterfaceSpecUtil.h"
29 #include "utils/StringUtil.h"
30
31 using namespace std;
32 using namespace android;
33
34 namespace android {
35 namespace vts {
36
37 const char* const HalHidlCodeGen::kInstanceVariableName = "hw_binder_proxy_";
38
GenerateCppBodyCallbackFunction(Formatter & out,const ComponentSpecificationMessage & message,const string &)39 void HalHidlCodeGen::GenerateCppBodyCallbackFunction(Formatter& out,
40 const ComponentSpecificationMessage& message,
41 const string& /*fuzzer_extended_class_name*/) {
42 if (endsWith(message.component_name(), "Callback")) {
43 out << "\n";
44 FQName component_fq_name = GetFQName(message);
45 for (const auto& api : message.interface().api()) {
46 // Generate return statement.
47 if (CanElideCallback(api)) {
48 out << "::android::hardware::Return<"
49 << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
50 } else {
51 out << "::android::hardware::Return<void> ";
52 }
53 // Generate function call.
54 string full_method_name = "Vts_" + component_fq_name.tokenName() + "::"
55 + api.name();
56 out << full_method_name << "(\n";
57 out.indent();
58 for (int index = 0; index < api.arg_size(); index++) {
59 const auto& arg = api.arg(index);
60 if (!isConstType(arg.type())) {
61 out << GetCppVariableType(arg, &message);
62 } else {
63 out << GetCppVariableType(arg, &message, true);
64 }
65 out << " arg" << index;
66 if (index != (api.arg_size() - 1))
67 out << ",\n";
68 }
69 if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
70 out << ") {" << "\n";
71 } else { // handle the case of callbacks.
72 out << (api.arg_size() != 0 ? ", " : "");
73 out << "std::function<void(";
74 for (int index = 0; index < api.return_type_hidl_size(); index++) {
75 const auto& return_val = api.return_type_hidl(index);
76 if (!isConstType(return_val.type())) {
77 out << GetCppVariableType(return_val, &message);
78 } else {
79 out << GetCppVariableType(return_val, &message, true);
80 }
81 out << " arg" << index;
82 if (index != (api.return_type_hidl_size() - 1))
83 out << ",";
84 }
85 out << ")>) {" << "\n";
86 }
87 out << "cout << \"" << api.name() << " called\" << endl;" << "\n";
88 out << "AndroidSystemCallbackRequestMessage callback_message;" << "\n";
89 out << "callback_message.set_id(GetCallbackID(\"" << api.name() << "\"));" << "\n";
90 out << "callback_message.set_name(\"" << full_method_name << "\");" << "\n";
91 for (int index = 0; index < api.arg_size(); index++) {
92 out << "VariableSpecificationMessage* var_msg" << index << " = "
93 << "callback_message.add_arg();\n";
94 GenerateSetResultCodeForTypedVariable(out, api.arg(index),
95 "var_msg" + std::to_string(index),
96 "arg" + std::to_string(index));
97 }
98 out << "RpcCallToAgent(callback_message, callback_socket_name_);" << "\n";
99
100 if (api.return_type_hidl_size() == 0
101 || api.return_type_hidl(0).type() == TYPE_VOID) {
102 out << "return ::android::hardware::Void();" << "\n";
103 } else {
104 out << "return hardware::Status::ok();" << "\n";
105 }
106 out.unindent();
107 out << "}" << "\n";
108 out << "\n";
109 }
110
111 string component_name_token = "Vts_" + component_fq_name.tokenName();
112 out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
113 << component_name_token << "(const string& callback_socket_name)";
114 out << " {" << "\n";
115 out.indent();
116 out << "static sp<" << component_fq_name.cppName() << "> result;\n";
117 out << "result = new " << component_name_token << "(callback_socket_name);"
118 << "\n";
119 out << "return result;\n";
120 out.unindent();
121 out << "}" << "\n" << "\n";
122 }
123 }
124
GenerateScalarTypeInC(Formatter & out,const string & type)125 void HalHidlCodeGen::GenerateScalarTypeInC(Formatter& out, const string& type) {
126 if (type == "bool_t") {
127 out << "bool";
128 } else if (type == "int8_t" ||
129 type == "uint8_t" ||
130 type == "int16_t" ||
131 type == "uint16_t" ||
132 type == "int32_t" ||
133 type == "uint32_t" ||
134 type == "int64_t" ||
135 type == "uint64_t" ||
136 type == "size_t") {
137 out << type;
138 } else if (type == "float_t") {
139 out << "float";
140 } else if (type == "double_t") {
141 out << "double";
142 } else if (type == "char_pointer") {
143 out << "char*";
144 } else if (type == "void_pointer") {
145 out << "void*";
146 } else {
147 cerr << __func__ << ":" << __LINE__
148 << " unsupported scalar type " << type << "\n";
149 exit(-1);
150 }
151 }
152
153
GenerateCppBodyFuzzFunction(Formatter & out,const ComponentSpecificationMessage &,const string & fuzzer_extended_class_name)154 void HalHidlCodeGen::GenerateCppBodyFuzzFunction(
155 Formatter& out, const ComponentSpecificationMessage& /*message*/,
156 const string& fuzzer_extended_class_name) {
157 out << "bool " << fuzzer_extended_class_name << "::Fuzz(" << "\n";
158 out << " FunctionSpecificationMessage* func_msg," << "\n";
159 out << " void** result, const string& callback_socket_name) {\n";
160 out.indent();
161 out << "return true;\n";
162 out.unindent();
163 out << "}\n";
164 }
165
GenerateDriverFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)166 void HalHidlCodeGen::GenerateDriverFunctionImpl(Formatter& out,
167 const ComponentSpecificationMessage& message,
168 const string& fuzzer_extended_class_name) {
169 if (message.component_name() != "types"
170 && !endsWith(message.component_name(), "Callback")) {
171 out << "bool " << fuzzer_extended_class_name << "::CallFunction("
172 << "const FunctionSpecificationMessage& func_msg, "
173 << "const string& callback_socket_name, "
174 << "FunctionSpecificationMessage* result_msg) {\n";
175 out.indent();
176
177 out << "const char* func_name = func_msg.name().c_str();" << "\n";
178 out << "cout << \"Function: \" << __func__ << \" \" << func_name << endl;"
179 << "\n";
180
181 for (auto const& api : message.interface().api()) {
182 GenerateDriverImplForMethod(out, message, api);
183 }
184
185 GenerateDriverImplForReservedMethods(out);
186
187 out << "return false;\n";
188 out.unindent();
189 out << "}\n";
190 }
191 }
192
GenerateDriverImplForReservedMethods(Formatter & out)193 void HalHidlCodeGen::GenerateDriverImplForReservedMethods(Formatter& out) {
194 // Generate call for reserved method: notifySyspropsChanged.
195 out << "if (!strcmp(func_name, \"notifySyspropsChanged\")) {\n";
196 out.indent();
197
198 out << "cout << \"Call notifySyspropsChanged\" << endl;" << "\n";
199 out << kInstanceVariableName << "->notifySyspropsChanged();\n";
200 out << "result_msg->set_name(\"notifySyspropsChanged\");\n";
201 out << "cout << \"called\" << endl;\n";
202 out << "return true;\n";
203
204 out.unindent();
205 out << "}\n";
206 // TODO(zhuoyao): Add generation code for other reserved method,
207 // e.g interfaceChain
208 }
209
GenerateDriverImplForMethod(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)210 void HalHidlCodeGen::GenerateDriverImplForMethod(Formatter& out,
211 const ComponentSpecificationMessage& message,
212 const FunctionSpecificationMessage& func_msg) {
213 out << "if (!strcmp(func_name, \"" << func_msg.name() << "\")) {\n";
214 out.indent();
215 // Process the arguments.
216 for (int i = 0; i < func_msg.arg_size(); i++) {
217 const auto& arg = func_msg.arg(i);
218 string cur_arg_name = "arg" + std::to_string(i);
219 string var_type;
220 if (arg.type() == TYPE_ARRAY || arg.type() == TYPE_VECTOR) {
221 var_type = GetCppVariableType(arg, &message, true);
222 var_type = var_type.substr(5, var_type.length() - 6);
223 } else {
224 var_type = GetCppVariableType(arg, &message);
225 }
226 out << var_type << " " << cur_arg_name << ";\n";
227 if (arg.type() == TYPE_SCALAR) {
228 out << cur_arg_name << " = 0;\n";
229 }
230 GenerateDriverImplForTypedVariable(
231 out, arg, cur_arg_name, "func_msg.arg(" + std::to_string(i) + ")");
232 }
233
234 GenerateCodeToStartMeasurement(out);
235 // may need to check whether the function is actually defined.
236 out << "cout << \"Call an API\" << endl;" << "\n";
237 out << "cout << \"local_device = \" << " << kInstanceVariableName << ".get()"
238 << " << endl;\n";
239
240 // Define the return results and call the HAL function.
241 for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
242 const auto& return_type = func_msg.return_type_hidl(index);
243 out << GetCppVariableType(return_type, &message) << " result" << index
244 << ";\n";
245 }
246 if (CanElideCallback(func_msg)) {
247 out << "result0 = ";
248 GenerateHalFunctionCall(out, message, func_msg);
249 } else {
250 GenerateHalFunctionCall(out, message, func_msg);
251 }
252
253 GenerateCodeToStopMeasurement(out);
254
255 // Set the return results value to the proto message.
256 out << "result_msg->set_name(\"" << func_msg.name() << "\");\n";
257 for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
258 out << "VariableSpecificationMessage* result_val_" << index << " = "
259 << "result_msg->add_return_type_hidl();\n";
260 GenerateSetResultCodeForTypedVariable(out, func_msg.return_type_hidl(index),
261 "result_val_" + std::to_string(index),
262 "result" + std::to_string(index));
263 }
264
265 out << "cout << \"called\" << endl;\n";
266 out << "return true;\n";
267 out.unindent();
268 out << "}\n";
269 }
270
GenerateHalFunctionCall(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)271 void HalHidlCodeGen::GenerateHalFunctionCall(Formatter& out,
272 const ComponentSpecificationMessage& message,
273 const FunctionSpecificationMessage& func_msg) {
274 out << kInstanceVariableName << "->" << func_msg.name() << "(";
275 for (int index = 0; index < func_msg.arg_size(); index++) {
276 out << "arg" << index;
277 if (index != (func_msg.arg_size() - 1)) out << ",";
278 }
279 if (func_msg.return_type_hidl_size()== 0 || CanElideCallback(func_msg)) {
280 out << ");\n";
281 } else {
282 out << (func_msg.arg_size() != 0 ? ", " : "");
283 GenerateSyncCallbackFunctionImpl(out, message, func_msg);
284 out << ");\n";
285 }
286 }
287
GenerateSyncCallbackFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const FunctionSpecificationMessage & func_msg)288 void HalHidlCodeGen::GenerateSyncCallbackFunctionImpl(Formatter& out,
289 const ComponentSpecificationMessage& message,
290 const FunctionSpecificationMessage& func_msg) {
291 out << "[&](";
292 for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
293 const auto& return_val = func_msg.return_type_hidl(index);
294 if (!isConstType(return_val.type())) {
295 out << GetCppVariableType(return_val, &message);
296 } else {
297 out << GetCppVariableType(return_val, &message, true);
298 }
299 out << " arg" << index;
300 if (index != (func_msg.return_type_hidl_size() - 1)) out << ",";
301 }
302 out << "){\n";
303 out.indent();
304 out << "cout << \"callback " << func_msg.name() << " called\""
305 << " << endl;\n";
306
307 for (int index = 0; index < func_msg.return_type_hidl_size(); index++) {
308 const auto& return_val = func_msg.return_type_hidl(index);
309 if (return_val.type() != TYPE_FMQ_SYNC
310 && return_val.type() != TYPE_FMQ_UNSYNC)
311 out << "result" << index << " = arg" << index << ";\n";
312 }
313 out.unindent();
314 out << "}";
315 }
316
GenerateCppBodyGetAttributeFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)317 void HalHidlCodeGen::GenerateCppBodyGetAttributeFunction(
318 Formatter& out, const ComponentSpecificationMessage& message,
319 const string& fuzzer_extended_class_name) {
320 if (message.component_name() != "types" &&
321 !endsWith(message.component_name(), "Callback")) {
322 out << "bool " << fuzzer_extended_class_name << "::GetAttribute(" << "\n";
323 out << " FunctionSpecificationMessage* func_msg," << "\n";
324 out << " void** result) {" << "\n";
325
326 // TOOD: impl
327 out << " cerr << \"attribute not found\" << endl;" << "\n";
328 out << " return false;" << "\n";
329 out << "}" << "\n";
330 }
331 }
332
GenerateClassConstructionFunction(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)333 void HalHidlCodeGen::GenerateClassConstructionFunction(Formatter& out,
334 const ComponentSpecificationMessage& message,
335 const string& fuzzer_extended_class_name) {
336 out << fuzzer_extended_class_name << "() : FuzzerBase(";
337 if (message.component_name() != "types") {
338 out << "HAL_HIDL), " << kInstanceVariableName << "()";
339 } else {
340 out << "HAL_HIDL)";
341 }
342 out << " {}" << "\n";
343 }
344
GenerateHeaderGlobalFunctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message)345 void HalHidlCodeGen::GenerateHeaderGlobalFunctionDeclarations(Formatter& out,
346 const ComponentSpecificationMessage& message) {
347 if (message.component_name() != "types"
348 && !endsWith(message.component_name(), "Callback")) {
349 DriverCodeGenBase::GenerateHeaderGlobalFunctionDeclarations(out, message);
350 }
351 }
352
GenerateCppBodyGlobalFunctions(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)353 void HalHidlCodeGen::GenerateCppBodyGlobalFunctions(Formatter& out,
354 const ComponentSpecificationMessage& message,
355 const string& fuzzer_extended_class_name) {
356 if (message.component_name() != "types"
357 && !endsWith(message.component_name(), "Callback")) {
358 DriverCodeGenBase::GenerateCppBodyGlobalFunctions(
359 out, message, fuzzer_extended_class_name);
360 }
361 }
362
GenerateClassHeader(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)363 void HalHidlCodeGen::GenerateClassHeader(Formatter& out,
364 const ComponentSpecificationMessage& message,
365 const string& fuzzer_extended_class_name) {
366 if (message.component_name() != "types"
367 && !endsWith(message.component_name(), "Callback")) {
368 for (const auto attribute : message.interface().attribute()) {
369 GenerateAllFunctionDeclForAttribute(out, attribute);
370 }
371 DriverCodeGenBase::GenerateClassHeader(out, message,
372 fuzzer_extended_class_name);
373 } else if (message.component_name() == "types") {
374 for (const auto attribute : message.attribute()) {
375 GenerateAllFunctionDeclForAttribute(out, attribute);
376 };
377 } else if (endsWith(message.component_name(), "Callback")) {
378 for (const auto attribute : message.interface().attribute()) {
379 GenerateAllFunctionDeclForAttribute(out, attribute);
380 }
381
382 out << "\n";
383 FQName component_fq_name = GetFQName(message);
384 string component_name_token = "Vts_" + component_fq_name.tokenName();;
385 out << "class " << component_name_token << " : public "
386 << component_fq_name.cppName() << ", public FuzzerCallbackBase {" << "\n";
387 out << " public:" << "\n";
388 out.indent();
389 out << component_name_token << "(const string& callback_socket_name)\n"
390 << " : callback_socket_name_(callback_socket_name) {};" << "\n";
391 out << "\n";
392 out << "virtual ~" << component_name_token << "()"
393 << " = default;" << "\n";
394 out << "\n";
395 for (const auto& api : message.interface().api()) {
396 // Generate return statement.
397 if (CanElideCallback(api)) {
398 out << "::android::hardware::Return<"
399 << GetCppVariableType(api.return_type_hidl(0), &message) << "> ";
400 } else {
401 out << "::android::hardware::Return<void> ";
402 }
403 // Generate function call.
404 out << api.name() << "(\n";
405 out.indent();
406 for (int index = 0; index < api.arg_size(); index++) {
407 const auto& arg = api.arg(index);
408 if (!isConstType(arg.type())) {
409 out << GetCppVariableType(arg, &message);
410 } else {
411 out << GetCppVariableType(arg, &message, true);
412 }
413 out << " arg" << index;
414 if (index != (api.arg_size() - 1))
415 out << ",\n";
416 }
417 if (api.return_type_hidl_size() == 0 || CanElideCallback(api)) {
418 out << ") override;" << "\n\n";
419 } else { // handle the case of callbacks.
420 out << (api.arg_size() != 0 ? ", " : "");
421 out << "std::function<void(";
422 for (int index = 0; index < api.return_type_hidl_size(); index++) {
423 const auto& return_val = api.return_type_hidl(index);
424 if (!isConstType(return_val.type())) {
425 out << GetCppVariableType(return_val, &message);
426 } else {
427 out << GetCppVariableType(return_val, &message, true);
428 }
429 out << " arg" << index;
430 if (index != (api.return_type_hidl_size() - 1))
431 out << ",";
432 }
433 out << ")>) override;" << "\n\n";
434 }
435 out.unindent();
436 }
437 out << "\n";
438 out.unindent();
439 out << " private:" << "\n";
440 out.indent();
441 out << "const string& callback_socket_name_;" << "\n";
442 out.unindent();
443 out << "};" << "\n";
444 out << "\n";
445
446 out << "sp<" << component_fq_name.cppName() << "> VtsFuzzerCreate"
447 << component_name_token << "(const string& callback_socket_name);"
448 << "\n";
449 out << "\n";
450 }
451 }
452
GenerateClassImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)453 void HalHidlCodeGen::GenerateClassImpl(Formatter& out,
454 const ComponentSpecificationMessage& message,
455 const string& fuzzer_extended_class_name) {
456 if (message.component_name() != "types"
457 && !endsWith(message.component_name(), "Callback")) {
458 for (auto attribute : message.interface().attribute()) {
459 GenerateAllFunctionImplForAttribute(out, attribute);
460 }
461 GenerateGetServiceImpl(out, message, fuzzer_extended_class_name);
462 DriverCodeGenBase::GenerateClassImpl(out, message,
463 fuzzer_extended_class_name);
464 } else if (message.component_name() == "types") {
465 for (auto attribute : message.attribute()) {
466 GenerateAllFunctionImplForAttribute(out, attribute);
467 }
468 } else if (endsWith(message.component_name(), "Callback")) {
469 for (auto attribute : message.interface().attribute()) {
470 GenerateAllFunctionImplForAttribute(out, attribute);
471 }
472 GenerateCppBodyCallbackFunction(out, message, fuzzer_extended_class_name);
473 }
474 }
475
GenerateHeaderIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)476 void HalHidlCodeGen::GenerateHeaderIncludeFiles(Formatter& out,
477 const ComponentSpecificationMessage& message,
478 const string& fuzzer_extended_class_name) {
479 DriverCodeGenBase::GenerateHeaderIncludeFiles(out, message,
480 fuzzer_extended_class_name);
481
482 string package_path_self = message.package();
483 ReplaceSubString(package_path_self, ".", "/");
484 string version_self = GetVersionString(message.component_type_version());
485
486 out << "#include <" << package_path_self << "/"
487 << version_self << "/"
488 << message.component_name() << ".h>" << "\n";
489 out << "#include <hidl/HidlSupport.h>" << "\n";
490
491 for (const auto& import : message.import()) {
492 FQName import_name = FQName(import);
493 string package_path = import_name.package();
494 string package_version = import_name.version();
495 string component_name = import_name.name();
496 ReplaceSubString(package_path, ".", "/");
497
498 out << "#include <" << package_path << "/" << package_version << "/"
499 << component_name << ".h>\n";
500 if (package_path.find("android/hardware") != std::string::npos) {
501 if (component_name[0] == 'I') {
502 component_name = component_name.substr(1);
503 }
504 out << "#include <" << package_path << "/" << package_version << "/"
505 << component_name << ".vts.h>\n";
506 }
507 }
508 out << "\n\n";
509 }
510
GenerateSourceIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)511 void HalHidlCodeGen::GenerateSourceIncludeFiles(Formatter& out,
512 const ComponentSpecificationMessage& message,
513 const string& fuzzer_extended_class_name) {
514 DriverCodeGenBase::GenerateSourceIncludeFiles(out, message,
515 fuzzer_extended_class_name);
516 out << "#include <hidl/HidlSupport.h>\n";
517 string input_vfs_file_path(input_vts_file_path_);
518 string package_path = message.package();
519 ReplaceSubString(package_path, ".", "/");
520 out << "#include <" << package_path << "/"
521 << GetVersionString(message.component_type_version()) << "/"
522 << message.component_name() << ".h>" << "\n";
523 for (const auto& import : message.import()) {
524 FQName import_name = FQName(import);
525 string package_name = import_name.package();
526 string package_version = import_name.version();
527 string component_name = import_name.name();
528 string package_path = package_name;
529 ReplaceSubString(package_path, ".", "/");
530 if (package_name == message.package()
531 && package_version
532 == GetVersionString(message.component_type_version())) {
533 if (component_name == "types") {
534 out << "#include \""
535 << input_vfs_file_path.substr(
536 0, input_vfs_file_path.find_last_of("\\/"))
537 << "/types.vts.h\"\n";
538 } else {
539 out << "#include \""
540 << input_vfs_file_path.substr(
541 0, input_vfs_file_path.find_last_of("\\/")) << "/"
542 << component_name.substr(1) << ".vts.h\"\n";
543 }
544 } else {
545 out << "#include <" << package_path << "/" << package_version << "/"
546 << component_name << ".h>\n";
547 }
548 }
549 }
550
GenerateAdditionalFuctionDeclarations(Formatter & out,const ComponentSpecificationMessage & message,const string &)551 void HalHidlCodeGen::GenerateAdditionalFuctionDeclarations(Formatter& out,
552 const ComponentSpecificationMessage& message,
553 const string& /*fuzzer_extended_class_name*/) {
554 if (message.component_name() != "types"
555 && !endsWith(message.component_name(), "Callback")) {
556 out << "bool GetService(bool get_stub, const char* service_name);"
557 << "\n\n";
558 }
559 }
560
GeneratePrivateMemberDeclarations(Formatter & out,const ComponentSpecificationMessage & message)561 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out,
562 const ComponentSpecificationMessage& message) {
563 FQName fqname = GetFQName(message);
564 out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n";
565 }
566
GenerateRandomFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)567 void HalHidlCodeGen::GenerateRandomFunctionDeclForAttribute(Formatter& out,
568 const VariableSpecificationMessage& attribute) {
569 if (attribute.type() == TYPE_ENUM) {
570 if (attribute.enum_value().enumerator_size() == 0) {
571 // empty enum without any actual enumerator.
572 return;
573 }
574 string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
575 out << attribute.name() << " " << "Random" << attribute_name << "();\n";
576 }
577 }
578
GenerateRandomFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)579 void HalHidlCodeGen::GenerateRandomFunctionImplForAttribute(Formatter& out,
580 const VariableSpecificationMessage& attribute) {
581 // Random value generator
582 if (attribute.type() == TYPE_ENUM) {
583 if (attribute.enum_value().enumerator_size() == 0) {
584 // empty enum without any actual enumerator.
585 return;
586 }
587 string attribute_name = ClearStringWithNameSpaceAccess(attribute.name());
588 out << attribute.name() << " " << "Random" << attribute_name << "() {"
589 << "\n";
590 out.indent();
591 out << attribute.enum_value().scalar_type() << " choice = " << "("
592 << attribute.enum_value().scalar_type() << ") " << "rand() / "
593 << attribute.enum_value().enumerator().size() << ";" << "\n";
594 if (attribute.enum_value().scalar_type().find("u") != 0) {
595 out << "if (choice < 0) choice *= -1;" << "\n";
596 }
597 for (int index = 0; index < attribute.enum_value().enumerator().size();
598 index++) {
599 out << "if (choice == ";
600 out << "(" << attribute.enum_value().scalar_type() << ") ";
601 if (attribute.enum_value().scalar_type() == "int8_t") {
602 out << attribute.enum_value().scalar_value(index).int8_t();
603 } else if (attribute.enum_value().scalar_type() == "uint8_t") {
604 out << attribute.enum_value().scalar_value(index).uint8_t();
605 } else if (attribute.enum_value().scalar_type() == "int16_t") {
606 out << attribute.enum_value().scalar_value(index).int16_t();
607 } else if (attribute.enum_value().scalar_type() == "uint16_t") {
608 out << attribute.enum_value().scalar_value(index).uint16_t();
609 } else if (attribute.enum_value().scalar_type() == "int32_t") {
610 out << attribute.enum_value().scalar_value(index).int32_t();
611 } else if (attribute.enum_value().scalar_type() == "uint32_t") {
612 out << attribute.enum_value().scalar_value(index).uint32_t();
613 } else if (attribute.enum_value().scalar_type() == "int64_t") {
614 out << attribute.enum_value().scalar_value(index).int64_t();
615 } else if (attribute.enum_value().scalar_type() == "uint64_t") {
616 out << attribute.enum_value().scalar_value(index).uint64_t();
617 } else {
618 cerr << __func__ << ":" << __LINE__ << " ERROR unsupported enum type "
619 << attribute.enum_value().scalar_type() << "\n";
620 exit(-1);
621 }
622 out << ") return " << attribute.name() << "::"
623 << attribute.enum_value().enumerator(index) << ";" << "\n";
624 }
625 out << "return " << attribute.name() << "::"
626 << attribute.enum_value().enumerator(0) << ";" << "\n";
627 out.unindent();
628 out << "}" << "\n";
629 }
630 }
631
GenerateDriverDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)632 void HalHidlCodeGen::GenerateDriverDeclForAttribute(Formatter& out,
633 const VariableSpecificationMessage& attribute) {
634 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
635 // Recursively generate SetResult method implementation for all sub_types.
636 for (const auto sub_struct : attribute.sub_struct()) {
637 GenerateDriverDeclForAttribute(out, sub_struct);
638 }
639 for (const auto sub_union : attribute.sub_union()) {
640 GenerateDriverDeclForAttribute(out, sub_union);
641 }
642 string func_name = "MessageTo"
643 + ClearStringWithNameSpaceAccess(attribute.name());
644 out << "void " << func_name
645 << "(const VariableSpecificationMessage& var_msg, " << attribute.name()
646 << "* arg);\n";
647 } else if (attribute.type() == TYPE_ENUM) {
648 string func_name = "EnumValue"
649 + ClearStringWithNameSpaceAccess(attribute.name());
650 // Message to value converter
651 out << attribute.name() << " " << func_name
652 << "(const ScalarDataValueMessage& arg);\n";
653 } else {
654 cerr << __func__ << " unsupported attribute type " << attribute.type()
655 << "\n";
656 exit(-1);
657 }
658 }
659
GenerateDriverImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)660 void HalHidlCodeGen::GenerateDriverImplForAttribute(Formatter& out,
661 const VariableSpecificationMessage& attribute) {
662 switch (attribute.type()) {
663 case TYPE_ENUM:
664 {
665 string func_name = "EnumValue"
666 + ClearStringWithNameSpaceAccess(attribute.name());
667 // Message to value converter
668 out << attribute.name() << " " << func_name
669 << "(const ScalarDataValueMessage& arg) {\n";
670 out.indent();
671 out << "return (" << attribute.name() << ") arg."
672 << attribute.enum_value().scalar_type() << "();\n";
673 out.unindent();
674 out << "}" << "\n";
675 break;
676 }
677 case TYPE_STRUCT:
678 {
679 // Recursively generate driver implementation method for all sub_types.
680 for (const auto sub_struct : attribute.sub_struct()) {
681 GenerateDriverImplForAttribute(out, sub_struct);
682 }
683 string func_name = "MessageTo"
684 + ClearStringWithNameSpaceAccess(attribute.name());
685 out << "void " << func_name
686 << "(const VariableSpecificationMessage& var_msg, "
687 << attribute.name() << "* arg) {" << "\n";
688 out.indent();
689 int struct_index = 0;
690 for (const auto& struct_value : attribute.struct_value()) {
691 GenerateDriverImplForTypedVariable(
692 out, struct_value, "arg->" + struct_value.name(),
693 "var_msg.struct_value(" + std::to_string(struct_index) + ")");
694 struct_index++;
695 }
696 out.unindent();
697 out << "}\n";
698 break;
699 }
700 case TYPE_UNION:
701 {
702 // Recursively generate driver implementation method for all sub_types.
703 for (const auto sub_union : attribute.sub_union()) {
704 GenerateDriverImplForAttribute(out, sub_union);
705 }
706 string func_name = "MessageTo"
707 + ClearStringWithNameSpaceAccess(attribute.name());
708 out << "void " << func_name
709 << "(const VariableSpecificationMessage& var_msg, "
710 << attribute.name() << "* arg) {" << "\n";
711 out.indent();
712 int union_index = 0;
713 for (const auto& union_value : attribute.union_value()) {
714 out << "if (var_msg.union_value(" << union_index << ").name() == \""
715 << union_value.name() << "\") {" << "\n";
716 out.indent();
717 GenerateDriverImplForTypedVariable(
718 out, union_value, "arg->" + union_value.name(),
719 "var_msg.union_value(" + std::to_string(union_index) + ")");
720 union_index++;
721 out.unindent();
722 out << "}" << "\n";
723 }
724 out.unindent();
725 out << "}\n";
726 break;
727 }
728 default:
729 {
730 cerr << __func__ << " unsupported attribute type " << attribute.type()
731 << "\n";
732 exit(-1);
733 }
734 }
735 }
736
GenerateGetServiceImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)737 void HalHidlCodeGen::GenerateGetServiceImpl(Formatter& out,
738 const ComponentSpecificationMessage& message,
739 const string& fuzzer_extended_class_name) {
740 out << "bool " << fuzzer_extended_class_name
741 << "::GetService(bool get_stub, const char* service_name) {" << "\n";
742 out.indent();
743 out << "static bool initialized = false;" << "\n";
744 out << "if (!initialized) {" << "\n";
745 out.indent();
746 out << "cout << \"[agent:hal] HIDL getService\" << endl;" << "\n";
747 out << "if (service_name) {\n"
748 << " cout << \" - service name: \" << service_name << endl;" << "\n"
749 << "}\n";
750 FQName fqname = GetFQName(message);
751 out << kInstanceVariableName << " = " << fqname.cppName() << "::getService("
752 << "service_name, get_stub);" << "\n";
753 out << "cout << \"[agent:hal] " << kInstanceVariableName << " = \" << "
754 << kInstanceVariableName << ".get() << endl;" << "\n";
755 out << "initialized = true;" << "\n";
756 out.unindent();
757 out << "}" << "\n";
758 out << "return true;" << "\n";
759 out.unindent();
760 out << "}" << "\n" << "\n";
761 }
762
GenerateDriverImplForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & arg_name,const string & arg_value_name)763 void HalHidlCodeGen::GenerateDriverImplForTypedVariable(Formatter& out,
764 const VariableSpecificationMessage& val, const string& arg_name,
765 const string& arg_value_name) {
766 switch (val.type()) {
767 case TYPE_SCALAR:
768 {
769 out << arg_name << " = " << arg_value_name << ".scalar_value()."
770 << val.scalar_type() << "();\n";
771 break;
772 }
773 case TYPE_STRING:
774 {
775 out << arg_name << " = ::android::hardware::hidl_string("
776 << arg_value_name << ".string_value().message());\n";
777 break;
778 }
779 case TYPE_ENUM:
780 {
781 if (val.has_predefined_type()) {
782 string func_name = "EnumValue"
783 + ClearStringWithNameSpaceAccess(val.predefined_type());
784 out << arg_name << " = " << func_name << "(" << arg_value_name
785 << ".scalar_value());\n";
786 } else {
787 out << arg_name << " = (" << val.name() << ")" << arg_value_name << "."
788 << "enum_value().scalar_value(0)." << val.enum_value().scalar_type()
789 << "();\n";
790 }
791 break;
792 }
793 case TYPE_MASK:
794 {
795 out << arg_name << " = " << arg_value_name << ".scalar_value()."
796 << val.scalar_type() << "();\n";
797 break;
798 }
799 case TYPE_VECTOR:
800 {
801 out << arg_name << ".resize(" << arg_value_name
802 << ".vector_value_size());\n";
803 out << "for (int i = 0; i <" << arg_value_name
804 << ".vector_value_size(); i++) {\n";
805 out.indent();
806 GenerateDriverImplForTypedVariable(out, val.vector_value(0),
807 arg_name + "[i]",
808 arg_value_name + ".vector_value(i)");
809 out.unindent();
810 out << "}\n";
811 break;
812 }
813 case TYPE_ARRAY:
814 {
815 out << "for (int i = 0; i < " << arg_value_name
816 << ".vector_value_size(); i++) {\n";
817 out.indent();
818 GenerateDriverImplForTypedVariable(out, val.vector_value(0),
819 arg_name + "[i]",
820 arg_value_name + ".vector_value(i)");
821 out.unindent();
822 out << "}\n";
823 break;
824 }
825 case TYPE_STRUCT:
826 {
827 if (val.has_predefined_type()) {
828 string func_name = "MessageTo"
829 + ClearStringWithNameSpaceAccess(val.predefined_type());
830 out << func_name << "(" << arg_value_name << ", &("
831 << arg_name << "));\n";
832 } else {
833 int struct_index = 0;
834 for (const auto struct_field : val.struct_value()) {
835 string struct_field_name = arg_name + "." + struct_field.name();
836 string struct_field_value_name = arg_value_name + ".struct_value("
837 + std::to_string(struct_index) + ")";
838 GenerateDriverImplForTypedVariable(out, struct_field,
839 struct_field_name,
840 struct_field_value_name);
841 struct_index++;
842 }
843 }
844 break;
845 }
846 case TYPE_UNION:
847 {
848 if (val.has_predefined_type()) {
849 string func_name = "MessageTo"
850 + ClearStringWithNameSpaceAccess(val.predefined_type());
851 out << func_name << "(" << arg_value_name << ", &(" << arg_name
852 << "));\n";
853 } else {
854 int union_index = 0;
855 for (const auto union_field : val.union_value()) {
856 string union_field_name = arg_name + "." + union_field.name();
857 string union_field_value_name = arg_value_name + ".union_value("
858 + std::to_string(union_index) + ")";
859 GenerateDriverImplForTypedVariable(out, union_field, union_field_name,
860 union_field_value_name);
861 union_index++;
862 }
863 }
864 break;
865 }
866 case TYPE_HIDL_CALLBACK:
867 {
868 string type_name = val.predefined_type();
869 ReplaceSubString(type_name, "::", "_");
870
871 out << arg_name << " = VtsFuzzerCreateVts" << type_name
872 << "(callback_socket_name);\n";
873 out << "static_cast<" << "Vts" + type_name << "*>(" << arg_name
874 << ".get())->Register(" << arg_value_name << ");\n";
875 break;
876 }
877 case TYPE_HANDLE:
878 {
879 out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
880 break;
881 }
882 case TYPE_HIDL_INTERFACE:
883 {
884 out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
885 break;
886 }
887 case TYPE_HIDL_MEMORY:
888 {
889 out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
890 break;
891 }
892 case TYPE_POINTER:
893 {
894 out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
895 break;
896 }
897 case TYPE_FMQ_SYNC:
898 {
899 out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
900 break;
901 }
902 case TYPE_FMQ_UNSYNC:
903 {
904 out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
905 break;
906 }
907 case TYPE_REF:
908 {
909 out << "/* ERROR: TYPE_REF is not supported yet. */\n";
910 break;
911 }
912 default:
913 {
914 cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
915 exit(-1);
916 }
917 }
918 }
919
920 // TODO(zhuoyao): Verify results based on verification rules instead of perform
921 // an exact match.
GenerateVerificationFunctionImpl(Formatter & out,const ComponentSpecificationMessage & message,const string & fuzzer_extended_class_name)922 void HalHidlCodeGen::GenerateVerificationFunctionImpl(Formatter& out,
923 const ComponentSpecificationMessage& message,
924 const string& fuzzer_extended_class_name) {
925 if (message.component_name() != "types"
926 && !endsWith(message.component_name(), "Callback")) {
927 // Generate the main profiler function.
928 out << "\nbool " << fuzzer_extended_class_name
929 << "::VerifyResults(const FunctionSpecificationMessage& expected_result, "
930 << "const FunctionSpecificationMessage& actual_result) {\n";
931 out.indent();
932 for (const FunctionSpecificationMessage api : message.interface().api()) {
933 out << "if (!strcmp(actual_result.name().c_str(), \"" << api.name()
934 << "\")) {\n";
935 out.indent();
936 out << "if (actual_result.return_type_hidl_size() != "
937 << "expected_result.return_type_hidl_size() "
938 << ") { return false; }\n";
939 for (int i = 0; i < api.return_type_hidl_size(); i++) {
940 std::string expected_result = "expected_result.return_type_hidl("
941 + std::to_string(i) + ")";
942 std::string actual_result = "actual_result.return_type_hidl("
943 + std::to_string(i) + ")";
944 GenerateVerificationCodeForTypedVariable(out, api.return_type_hidl(i),
945 expected_result,
946 actual_result);
947 }
948 out << "return true;\n";
949 out.unindent();
950 out << "}\n";
951 }
952 out << "return false;\n";
953 out.unindent();
954 out << "}\n\n";
955 }
956 }
957
GenerateVerificationCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & expected_result,const string & actual_result)958 void HalHidlCodeGen::GenerateVerificationCodeForTypedVariable(Formatter& out,
959 const VariableSpecificationMessage& val, const string& expected_result,
960 const string& actual_result) {
961 switch (val.type()) {
962 case TYPE_SCALAR:
963 {
964 out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
965 << "() != " << expected_result << ".scalar_value()."
966 << val.scalar_type() << "()) { return false; }\n";
967 break;
968 }
969 case TYPE_STRING:
970 {
971 out << "if (strcmp(" << actual_result
972 << ".string_value().message().c_str(), " << expected_result
973 << ".string_value().message().c_str())!= 0)" << "{ return false; }\n";
974 break;
975 }
976 case TYPE_ENUM:
977 {
978 if (val.has_predefined_type()) {
979 string func_name = "Verify"
980 + ClearStringWithNameSpaceAccess(val.predefined_type());
981 out << "if(!" << func_name << "(" << expected_result << ", "
982 << actual_result << ")) { return false; }\n";
983 } else {
984 out << "if (" << actual_result << ".scalar_value()."
985 << val.enum_value().scalar_type() << "() != " << expected_result
986 << ".scalar_value()." << val.enum_value().scalar_type()
987 << "()) { return false; }\n";
988 }
989 break;
990 }
991 case TYPE_MASK:
992 {
993 out << "if (" << actual_result << ".scalar_value()." << val.scalar_type()
994 << "() != " << expected_result << ".scalar_value()."
995 << val.scalar_type() << "()) { return false; }\n";
996 break;
997 }
998 case TYPE_VECTOR:
999 {
1000 out << "if (" << actual_result << ".vector_value_size() != "
1001 << expected_result << ".vector_value_size()) {\n";
1002 out.indent();
1003 out << "cerr << \"Verification failed for vector size. expected: \" << "
1004 << expected_result << ".vector_value_size() << \" actual: \" << "
1005 << actual_result << ".vector_value_size();\n";
1006 out << "return false;\n";
1007 out.unindent();
1008 out << "}\n";
1009 out << "for (int i = 0; i <" << expected_result
1010 << ".vector_value_size(); i++) {\n";
1011 out.indent();
1012 GenerateVerificationCodeForTypedVariable(
1013 out, val.vector_value(0), expected_result + ".vector_value(i)",
1014 actual_result + ".vector_value(i)");
1015 out.unindent();
1016 out << "}\n";
1017 break;
1018 }
1019 case TYPE_ARRAY:
1020 {
1021 out << "if (" << actual_result << ".vector_value_size() != "
1022 << expected_result << ".vector_value_size()) {\n";
1023 out.indent();
1024 out << "cerr << \"Verification failed for vector size. expected: \" << "
1025 << expected_result << ".vector_value_size() << \" actual: \" << "
1026 << actual_result << ".vector_value_size();\n";
1027 out << "return false;\n";
1028 out.unindent();
1029 out << "}\n";
1030 out << "for (int i = 0; i < " << expected_result
1031 << ".vector_value_size(); i++) {\n";
1032 out.indent();
1033 GenerateVerificationCodeForTypedVariable(
1034 out, val.vector_value(0), expected_result + ".vector_value(i)",
1035 actual_result + ".vector_value(i)");
1036 out.unindent();
1037 out << "}\n";
1038 break;
1039 }
1040 case TYPE_STRUCT:
1041 {
1042 if (val.has_predefined_type()) {
1043 string func_name = "Verify"
1044 + ClearStringWithNameSpaceAccess(val.predefined_type());
1045 out << "if (!" << func_name << "(" << expected_result << ", "
1046 << actual_result << ")) { return false; }\n";
1047 } else {
1048 for (int i = 0; i < val.struct_value_size(); i++) {
1049 string struct_field_actual_result = actual_result + ".struct_value("
1050 + std::to_string(i) + ")";
1051 string struct_field_expected_result = expected_result
1052 + ".struct_value(" + std::to_string(i) + ")";
1053 GenerateVerificationCodeForTypedVariable(out, val.struct_value(i),
1054 struct_field_expected_result,
1055 struct_field_actual_result);
1056 }
1057 }
1058 break;
1059 }
1060 case TYPE_UNION:
1061 {
1062 if (val.has_predefined_type()) {
1063 string func_name = "Verify"
1064 + ClearStringWithNameSpaceAccess(val.predefined_type());
1065 out << "if (!" << func_name << "(" << expected_result << ", "
1066 << actual_result << ")) {return false; }\n";
1067 } else {
1068 for (int i = 0; i < val.union_value_size(); i++) {
1069 string union_field_actual_result = actual_result + ".union_value("
1070 + std::to_string(i) + ")";
1071 string union_field_expected_result = expected_result + ".union_value("
1072 + std::to_string(i) + ")";
1073 GenerateVerificationCodeForTypedVariable(out, val.union_value(i),
1074 union_field_expected_result,
1075 union_field_actual_result);
1076 }
1077 }
1078 break;
1079 }
1080 case TYPE_HIDL_CALLBACK:
1081 {
1082 out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
1083 break;
1084 }
1085 case TYPE_HANDLE:
1086 {
1087 out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
1088 break;
1089 }
1090 case TYPE_HIDL_INTERFACE:
1091 {
1092 out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
1093 break;
1094 }
1095 case TYPE_HIDL_MEMORY:
1096 {
1097 out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
1098 break;
1099 }
1100 case TYPE_POINTER:
1101 {
1102 out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
1103 break;
1104 }
1105 case TYPE_FMQ_SYNC:
1106 {
1107 out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
1108 break;
1109 }
1110 case TYPE_FMQ_UNSYNC:
1111 {
1112 out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
1113 break;
1114 }
1115 case TYPE_REF:
1116 {
1117 out << "/* ERROR: TYPE_REF is not supported yet. */\n";
1118 break;
1119 }
1120 default:
1121 {
1122 cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1123 exit(-1);
1124 }
1125 }
1126 }
1127
GenerateVerificationDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1128 void HalHidlCodeGen::GenerateVerificationDeclForAttribute(Formatter& out,
1129 const VariableSpecificationMessage& attribute) {
1130 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1131 // Recursively generate verification method implementation for all sub_types.
1132 for (const auto sub_struct : attribute.sub_struct()) {
1133 GenerateVerificationDeclForAttribute(out, sub_struct);
1134 }
1135 for (const auto sub_union : attribute.sub_union()) {
1136 GenerateVerificationDeclForAttribute(out, sub_union);
1137 }
1138 }
1139 std::string func_name = "bool Verify"
1140 + ClearStringWithNameSpaceAccess(attribute.name());
1141 out << func_name << "(const VariableSpecificationMessage& expected_result, "
1142 << "const VariableSpecificationMessage& actual_result);\n";
1143 }
1144
GenerateVerificationImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1145 void HalHidlCodeGen::GenerateVerificationImplForAttribute(Formatter& out,
1146 const VariableSpecificationMessage& attribute) {
1147 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1148 // Recursively generate verification method implementation for all sub_types.
1149 for (const auto sub_struct : attribute.sub_struct()) {
1150 GenerateVerificationImplForAttribute(out, sub_struct);
1151 }
1152 for (const auto sub_union : attribute.sub_union()) {
1153 GenerateVerificationImplForAttribute(out, sub_union);
1154 }
1155 }
1156 std::string func_name = "bool Verify"
1157 + ClearStringWithNameSpaceAccess(attribute.name());
1158 out << func_name << "(const VariableSpecificationMessage& expected_result, "
1159 << "const VariableSpecificationMessage& actual_result){\n";
1160 out.indent();
1161 GenerateVerificationCodeForTypedVariable(out, attribute, "expected_result",
1162 "actual_result");
1163 out << "return true;\n";
1164 out.unindent();
1165 out << "}\n\n";
1166 }
1167
1168 // TODO(zhuoyao): consider to generalize the pattern for
1169 // Verification/SetResult/DriverImpl.
GenerateSetResultCodeForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const string & result_msg,const string & result_value)1170 void HalHidlCodeGen::GenerateSetResultCodeForTypedVariable(Formatter& out,
1171 const VariableSpecificationMessage& val, const string& result_msg,
1172 const string& result_value) {
1173 switch (val.type()) {
1174 case TYPE_SCALAR:
1175 {
1176 out << result_msg << "->set_type(TYPE_SCALAR);\n";
1177 out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1178 << "\");\n";
1179 out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1180 << "(" << result_value << ");\n";
1181 break;
1182 }
1183 case TYPE_STRING:
1184 {
1185 out << result_msg << "->set_type(TYPE_STRING);\n";
1186 out << result_msg << "->mutable_string_value()->set_message" << "("
1187 << result_value << ".c_str());\n";
1188 out << result_msg << "->mutable_string_value()->set_length" << "("
1189 << result_value << ".size());\n";
1190 break;
1191 }
1192 case TYPE_ENUM:
1193 {
1194 out << result_msg << "->set_type(TYPE_ENUM);\n";
1195 if (val.has_predefined_type()) {
1196 string func_name = "SetResult"
1197 + ClearStringWithNameSpaceAccess(val.predefined_type());
1198 out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1199 } else {
1200 const string scalar_type = val.enum_value().scalar_type();
1201 out << result_msg << "->set_scalar_type(\"" << scalar_type << "\");\n";
1202 out << result_msg << "->mutable_scalar_value()->set_" << scalar_type
1203 << "(static_cast<" << scalar_type << ">(" << result_value
1204 << "));\n";
1205 }
1206 break;
1207 }
1208 case TYPE_MASK:
1209 {
1210 out << result_msg << "->set_type(TYPE_MASK);\n";
1211 out << result_msg << "->set_scalar_type(\"" << val.scalar_type()
1212 << "\");\n";
1213 out << result_msg << "->mutable_scalar_value()->set_" << val.scalar_type()
1214 << "(" << result_value << ");\n";
1215 break;
1216 }
1217 case TYPE_VECTOR:
1218 {
1219 out << result_msg << "->set_type(TYPE_VECTOR);\n";
1220 out << result_msg << "->set_vector_size(" << result_value
1221 << ".size());\n";
1222 out << "for (int i = 0; i < (int)" << result_value << ".size(); i++) {\n";
1223 out.indent();
1224 string vector_element_name = result_msg + "_vector_i";
1225 out << "auto *" << vector_element_name << " = " << result_msg
1226 << "->add_vector_value();\n";
1227 GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1228 vector_element_name,
1229 result_value + "[i]");
1230 out.unindent();
1231 out << "}\n";
1232 break;
1233 }
1234 case TYPE_ARRAY:
1235 {
1236 out << result_msg << "->set_type(TYPE_ARRAY);\n";
1237 out << result_msg << "->set_vector_size(" << val.vector_value_size()
1238 << ");\n";
1239 out << "for (int i = 0; i < " << val.vector_value_size() << "; i++) {\n";
1240 out.indent();
1241 string array_element_name = result_msg + "_array_i";
1242 out << "auto *" << array_element_name << " = " << result_msg
1243 << "->add_vector_value();\n";
1244 GenerateSetResultCodeForTypedVariable(out, val.vector_value(0),
1245 array_element_name,
1246 result_value + "[i]");
1247 out.unindent();
1248 out << "}\n";
1249 break;
1250 }
1251 case TYPE_STRUCT:
1252 {
1253 out << result_msg << "->set_type(TYPE_STRUCT);\n";
1254 if (val.has_predefined_type()) {
1255 string func_name = "SetResult"
1256 + ClearStringWithNameSpaceAccess(val.predefined_type());
1257 out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1258 } else {
1259 for (const auto struct_field : val.struct_value()) {
1260 string struct_field_name = result_msg + "_" + struct_field.name();
1261 out << "auto *" << struct_field_name << " = " << result_msg
1262 << "->add_struct_value();\n";
1263 GenerateSetResultCodeForTypedVariable(
1264 out, struct_field, struct_field_name,
1265 result_value + "." + struct_field.name());
1266 if (struct_field.has_name()) {
1267 out << struct_field_name << "->set_name(\""
1268 << struct_field.name() << "\");\n";
1269 }
1270 }
1271 }
1272 break;
1273 }
1274 case TYPE_UNION:
1275 {
1276 out << result_msg << "->set_type(TYPE_UNION);\n";
1277 if (val.has_predefined_type()) {
1278 string func_name = "SetResult"
1279 + ClearStringWithNameSpaceAccess(val.predefined_type());
1280 out << func_name << "(" << result_msg << ", " << result_value << ");\n";
1281 } else {
1282 for (const auto union_field : val.union_value()) {
1283 string union_field_name = result_msg + "_" + union_field.name();
1284 out << "auto *" << union_field_name << " = " << result_msg
1285 << "->add_union_value();\n";
1286 GenerateSetResultCodeForTypedVariable(
1287 out, union_field, union_field_name,
1288 result_value + "." + union_field.name());
1289 }
1290 }
1291 break;
1292 }
1293 case TYPE_HIDL_CALLBACK:
1294 {
1295 out << result_msg << "->set_type(TYPE_HIDL_CALLBACK);\n";
1296 out << "/* ERROR: TYPE_HIDL_CALLBACK is not supported yet. */\n";
1297 break;
1298 }
1299 case TYPE_HANDLE:
1300 {
1301 out << result_msg << "->set_type(TYPE_HANDLE);\n";
1302 out << "/* ERROR: TYPE_HANDLE is not supported yet. */\n";
1303 break;
1304 }
1305 case TYPE_HIDL_INTERFACE:
1306 {
1307 out << result_msg << "->set_type(TYPE_HIDL_INTERFACE);\n";
1308 out << "/* ERROR: TYPE_HIDL_INTERFACE is not supported yet. */\n";
1309 break;
1310 }
1311 case TYPE_HIDL_MEMORY:
1312 {
1313 out << result_msg << "->set_type(TYPE_HIDL_MEMORY);\n";
1314 out << "/* ERROR: TYPE_HIDL_MEMORY is not supported yet. */\n";
1315 break;
1316 }
1317 case TYPE_POINTER:
1318 {
1319 out << result_msg << "->set_type(TYPE_POINTER);\n";
1320 out << "/* ERROR: TYPE_POINTER is not supported yet. */\n";
1321 break;
1322 }
1323 case TYPE_FMQ_SYNC:
1324 {
1325 out << result_msg << "->set_type(TYPE_FMQ_SYNC);\n";
1326 out << "/* ERROR: TYPE_FMQ_SYNC is not supported yet. */\n";
1327 break;
1328 }
1329 case TYPE_FMQ_UNSYNC:
1330 {
1331 out << result_msg << "->set_type(TYPE_FMQ_UNSYNC);\n";
1332 out << "/* ERROR: TYPE_FMQ_UNSYNC is not supported yet. */\n";
1333 break;
1334 }
1335 case TYPE_REF:
1336 {
1337 out << result_msg << "->set_type(TYPE_REF);\n";
1338 out << "/* ERROR: TYPE_REF is not supported yet. */\n";
1339 break;
1340 }
1341 default:
1342 {
1343 cerr << __func__ << " ERROR: unsupported type " << val.type() << ".\n";
1344 exit(-1);
1345 }
1346 }
1347 }
1348
GenerateSetResultDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1349 void HalHidlCodeGen::GenerateSetResultDeclForAttribute(Formatter& out,
1350 const VariableSpecificationMessage& attribute) {
1351 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1352 // Recursively generate SetResult method implementation for all sub_types.
1353 for (const auto sub_struct : attribute.sub_struct()) {
1354 GenerateSetResultDeclForAttribute(out, sub_struct);
1355 }
1356 for (const auto sub_union : attribute.sub_union()) {
1357 GenerateSetResultDeclForAttribute(out, sub_union);
1358 }
1359 }
1360 string func_name = "void SetResult"
1361 + ClearStringWithNameSpaceAccess(attribute.name());
1362 out << func_name << "(VariableSpecificationMessage* result_msg, "
1363 << attribute.name() << " result_value);\n";
1364 }
1365
GenerateSetResultImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1366 void HalHidlCodeGen::GenerateSetResultImplForAttribute(Formatter& out,
1367 const VariableSpecificationMessage& attribute) {
1368 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION) {
1369 // Recursively generate SetResult method implementation for all sub_types.
1370 for (const auto sub_struct : attribute.sub_struct()) {
1371 GenerateSetResultImplForAttribute(out, sub_struct);
1372 }
1373 for (const auto sub_union : attribute.sub_union()) {
1374 GenerateSetResultImplForAttribute(out, sub_union);
1375 }
1376 }
1377 string func_name = "void SetResult"
1378 + ClearStringWithNameSpaceAccess(attribute.name());
1379 out << func_name << "(VariableSpecificationMessage* result_msg, "
1380 << attribute.name() << " result_value){\n";
1381 out.indent();
1382 GenerateSetResultCodeForTypedVariable(out, attribute, "result_msg",
1383 "result_value");
1384 out.unindent();
1385 out << "}\n\n";
1386 }
1387
GenerateAllFunctionDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1388 void HalHidlCodeGen::GenerateAllFunctionDeclForAttribute(Formatter& out,
1389 const VariableSpecificationMessage& attribute) {
1390 GenerateDriverDeclForAttribute(out, attribute);
1391 GenerateRandomFunctionDeclForAttribute(out, attribute);
1392 GenerateVerificationDeclForAttribute(out, attribute);
1393 GenerateSetResultDeclForAttribute(out, attribute);
1394 }
1395
GenerateAllFunctionImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)1396 void HalHidlCodeGen::GenerateAllFunctionImplForAttribute(Formatter& out,
1397 const VariableSpecificationMessage& attribute) {
1398 GenerateDriverImplForAttribute(out, attribute);
1399 GenerateRandomFunctionImplForAttribute(out, attribute);
1400 GenerateVerificationImplForAttribute(out, attribute);
1401 GenerateSetResultImplForAttribute(out, attribute);
1402 }
1403
CanElideCallback(const FunctionSpecificationMessage & func_msg)1404 bool HalHidlCodeGen::CanElideCallback(
1405 const FunctionSpecificationMessage& func_msg) {
1406 // Can't elide callback for void or tuple-returning methods
1407 if (func_msg.return_type_hidl_size() != 1) {
1408 return false;
1409 }
1410 const VariableType& type = func_msg.return_type_hidl(0).type();
1411 if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
1412 return false;
1413 }
1414 return isElidableType(type);
1415 }
1416
isElidableType(const VariableType & type)1417 bool HalHidlCodeGen::isElidableType(const VariableType& type) {
1418 if (type == TYPE_SCALAR || type == TYPE_ENUM || type == TYPE_MASK
1419 || type == TYPE_POINTER || type == TYPE_HIDL_INTERFACE
1420 || type == TYPE_VOID) {
1421 return true;
1422 }
1423 return false;
1424 }
1425
isConstType(const VariableType & type)1426 bool HalHidlCodeGen::isConstType(const VariableType& type) {
1427 if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
1428 return true;
1429 }
1430 if (isElidableType(type)) {
1431 return false;
1432 }
1433 return true;
1434 }
1435
1436 } // namespace vts
1437 } // namespace android
1438