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::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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 561 void HalHidlCodeGen::GeneratePrivateMemberDeclarations(Formatter& out, 562 const ComponentSpecificationMessage& message) { 563 FQName fqname = GetFQName(message); 564 out << "sp<" << fqname.cppName() << "> " << kInstanceVariableName << ";\n"; 565 } 566 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 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 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 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 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 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. 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 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 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 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. 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 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 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 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 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 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 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 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