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