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 "VtsCompilerUtils.h" 18 19 #include <limits.h> 20 #include <stdlib.h> 21 #include <sys/stat.h> 22 #include <sys/types.h> 23 #include <unistd.h> 24 25 #include <cstdint> 26 #include <fstream> 27 #include <iostream> 28 #include <sstream> 29 30 #include <google/protobuf/text_format.h> 31 32 #include "utils/InterfaceSpecUtil.h" 33 #include "utils/StringUtil.h" 34 35 #include "test/vts/proto/ComponentSpecificationMessage.pb.h" 36 37 using namespace std; 38 39 namespace android { 40 namespace vts { 41 42 string ComponentClassToString(int component_class) { 43 switch (component_class) { 44 case UNKNOWN_CLASS: 45 return "unknown_class"; 46 case HAL_CONVENTIONAL: 47 return "hal_conventional"; 48 case HAL_CONVENTIONAL_SUBMODULE: 49 return "hal_conventional_submodule"; 50 case HAL_HIDL: 51 return "hal_hidl"; 52 case HAL_HIDL_WRAPPED_CONVENTIONAL: 53 return "hal_hidl_wrapped_conventional"; 54 case HAL_LEGACY: 55 return "hal_legacy"; 56 case LIB_SHARED: 57 return "lib_shared"; 58 } 59 cerr << "error: invalid component_class " << component_class << endl; 60 exit(-1); 61 } 62 63 string ComponentTypeToString(int component_type) { 64 switch (component_type) { 65 case UNKNOWN_TYPE: 66 return "unknown_type"; 67 case AUDIO: 68 return "audio"; 69 case CAMERA: 70 return "camera"; 71 case GPS: 72 return "gps"; 73 case LIGHT: 74 return "light"; 75 case WIFI: 76 return "wifi"; 77 case MOBILE: 78 return "mobile"; 79 case BLUETOOTH: 80 return "bluetooth"; 81 case TV_INPUT: 82 return "tv_input"; 83 case NFC: 84 return "nfc"; 85 case VEHICLE: 86 return "vehicle"; 87 case VIBRATOR: 88 return "vibrator"; 89 case THERMAL: 90 return "thermal"; 91 case CONTEXTHUB: 92 return "contexthub"; 93 case SENSORS: 94 return "sensors"; 95 case VR: 96 return "vr"; 97 case GRAPHICS_ALLOCATOR: 98 return "graphics_allocator"; 99 case GRAPHICS_MAPPER: 100 return "graphics_mapper"; 101 case GRAPHICS_COMPOSER: 102 return "graphics_composer"; 103 case BIONIC_LIBM: 104 return "bionic_libm"; 105 case TV_CEC: 106 return "tv_cec"; 107 case RADIO: 108 return "radio"; 109 case MEDIA_OMX: 110 return "media_omx"; 111 case BIONIC_LIBC: 112 return "bionic_libc"; 113 case VNDK_LIBCUTILS: 114 return "vndk_libcutils"; 115 } 116 cerr << "error: invalid component_type " << component_type << endl; 117 exit(-1); 118 } 119 120 string GetCppVariableType(const std::string scalar_type_string) { 121 if (scalar_type_string == "void" || 122 scalar_type_string == "int32_t" || scalar_type_string == "uint32_t" || 123 scalar_type_string == "int8_t" || scalar_type_string == "uint8_t" || 124 scalar_type_string == "int64_t" || scalar_type_string == "uint64_t" || 125 scalar_type_string == "int16_t" || scalar_type_string == "uint16_t") { 126 return scalar_type_string; 127 } else if (scalar_type_string == "bool_t") { 128 return "bool"; 129 } else if (scalar_type_string == "float_t") { 130 return "float"; 131 } else if (scalar_type_string == "double_t") { 132 return "double"; 133 } else if (scalar_type_string == "ufloat") { 134 return "unsigned float"; 135 } else if (scalar_type_string == "udouble") { 136 return "unsigned double"; 137 } else if (scalar_type_string == "string") { 138 return "std::string"; 139 } else if (scalar_type_string == "pointer") { 140 return "void*"; 141 } else if (scalar_type_string == "char_pointer") { 142 return "char*"; 143 } else if (scalar_type_string == "uchar_pointer") { 144 return "unsigned char*"; 145 } else if (scalar_type_string == "void_pointer") { 146 return "void*"; 147 } else if (scalar_type_string == "function_pointer") { 148 return "void*"; 149 } 150 151 cerr << __func__ << ":" << __LINE__ << " " 152 << "error: unknown scalar_type " << scalar_type_string << endl; 153 exit(-1); 154 } 155 156 string GetCppVariableType(const VariableSpecificationMessage& arg, 157 bool generate_const) { 158 string result; 159 switch (arg.type()) { 160 case TYPE_VOID: 161 { 162 return "void"; 163 } 164 case TYPE_PREDEFINED: 165 { 166 result = arg.predefined_type(); 167 break; 168 } 169 case TYPE_SCALAR: 170 { 171 result = GetCppVariableType(arg.scalar_type()); 172 break; 173 } 174 case TYPE_STRING: 175 { 176 result = "::android::hardware::hidl_string"; 177 break; 178 } 179 case TYPE_ENUM: 180 { 181 if (!arg.has_enum_value() && arg.has_predefined_type()) { 182 result = arg.predefined_type(); 183 } else if (arg.has_enum_value() && arg.has_name()) { 184 result = arg.name(); // nested enum type. 185 } else { 186 cerr << __func__ << ":" << __LINE__ 187 << " ERROR no predefined_type set for enum variable" << endl; 188 exit(-1); 189 } 190 break; 191 } 192 case TYPE_VECTOR: 193 { 194 string element_type = GetCppVariableType(arg.vector_value(0)); 195 result = "::android::hardware::hidl_vec<" + element_type + ">"; 196 break; 197 } 198 case TYPE_ARRAY: 199 { 200 VariableSpecificationMessage cur_val = arg; 201 vector<int32_t> array_sizes; 202 while (cur_val.type() == TYPE_ARRAY) { 203 array_sizes.push_back(cur_val.vector_size()); 204 VariableSpecificationMessage temp = cur_val.vector_value(0); 205 cur_val = temp; 206 } 207 string element_type = GetCppVariableType(cur_val); 208 result = "::android::hardware::hidl_array<" + element_type + ", "; 209 for (size_t i = 0; i < array_sizes.size(); i++) { 210 result += to_string(array_sizes[i]); 211 if (i != array_sizes.size() - 1) result += ", "; 212 } 213 result += ">"; 214 break; 215 } 216 case TYPE_STRUCT: 217 { 218 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) { 219 result = arg.predefined_type(); 220 } else if (arg.has_struct_type()) { 221 result = arg.struct_type(); 222 } else if (arg.sub_struct_size() > 0 || arg.struct_value_size() > 0) { 223 result = arg.name(); 224 } else { 225 cerr << __func__ << ":" << __LINE__ << " ERROR" 226 << " no predefined_type, struct_type, nor sub_struct set" 227 << " for struct variable" 228 << " (arg name " << arg.name() << ")" << endl; 229 exit(-1); 230 } 231 break; 232 } 233 case TYPE_UNION: 234 { 235 if (arg.union_value_size() == 0 && arg.has_predefined_type()) { 236 result = arg.predefined_type(); 237 } else if (arg.has_union_type()) { 238 result = arg.union_type(); 239 } else { 240 cerr << __func__ << ":" << __LINE__ 241 << " ERROR no predefined_type or union_type set for union" 242 << " variable" << endl; 243 exit(-1); 244 } 245 break; 246 } 247 case TYPE_HIDL_CALLBACK: 248 { 249 if (arg.has_predefined_type()) { 250 result = "sp<" + arg.predefined_type() + ">"; 251 } else { 252 cerr << __func__ << ":" << __LINE__ 253 << " ERROR no predefined_type set for hidl callback variable" 254 << endl; 255 exit(-1); 256 } 257 break; 258 } 259 case TYPE_HANDLE: 260 { 261 result = "::android::hardware::hidl_handle"; 262 break; 263 } 264 case TYPE_HIDL_INTERFACE: 265 { 266 if (arg.has_predefined_type()) { 267 result = "sp<" + arg.predefined_type() + ">"; 268 } else { 269 cerr << __func__ << ":" << __LINE__ 270 << " ERROR no predefined_type set for hidl interface variable" 271 << endl; 272 exit(-1); 273 } 274 break; 275 } 276 case TYPE_MASK: 277 { 278 result = GetCppVariableType(arg.scalar_type()); 279 break; 280 } 281 case TYPE_HIDL_MEMORY: 282 { 283 result = "::android::hardware::hidl_memory"; 284 break; 285 } 286 case TYPE_POINTER: 287 { 288 result = "void*"; 289 if (generate_const) { 290 result = "const " + result; 291 } 292 return result; 293 } 294 case TYPE_FMQ_SYNC: 295 { 296 string element_type = GetCppVariableType(arg.fmq_value(0)); 297 result = "::android::hardware::MQDescriptorSync<" + element_type + ">"; 298 break; 299 } 300 case TYPE_FMQ_UNSYNC: 301 { 302 string element_type = GetCppVariableType(arg.fmq_value(0)); 303 result = "::android::hardware::MQDescriptorUnsync<" + element_type + ">"; 304 break; 305 } 306 case TYPE_REF: 307 { 308 VariableSpecificationMessage cur_val = arg; 309 int ref_depth = 0; 310 while (cur_val.type() == TYPE_REF) { 311 ref_depth++; 312 VariableSpecificationMessage temp = cur_val.ref_value(); 313 cur_val = temp; 314 } 315 string element_type = GetCppVariableType(cur_val); 316 result = element_type; 317 for (int i = 0; i < ref_depth; i++) { 318 result += " const*"; 319 } 320 return result; 321 break; 322 } 323 default: 324 { 325 cerr << __func__ << ":" << __LINE__ << " " << ": type " << arg.type() 326 << " not supported" << endl; 327 exit(-1); 328 } 329 } 330 if (generate_const) { 331 return "const " + result + "&"; 332 } 333 return result; 334 } 335 336 string GetConversionToProtobufFunctionName(VariableSpecificationMessage arg) { 337 if (arg.type() == TYPE_PREDEFINED) { 338 if (arg.predefined_type() == "camera_info_t*") { 339 return "ConvertCameraInfoToProtobuf"; 340 } else if (arg.predefined_type() == "hw_device_t**") { 341 return ""; 342 } else { 343 cerr << __FILE__ << ":" << __LINE__ << " " 344 << "error: unknown instance type " << arg.predefined_type() << endl; 345 } 346 } 347 cerr << __FUNCTION__ << ": non-supported type " << arg.type() << endl; 348 exit(-1); 349 } 350 351 string GetCppInstanceType( 352 const VariableSpecificationMessage& arg, 353 const string& msg, 354 const ComponentSpecificationMessage* message) { 355 switch(arg.type()) { 356 case TYPE_PREDEFINED: { 357 if (arg.predefined_type() == "struct light_state_t*") { 358 if (msg.length() == 0) { 359 return "GenerateLightState()"; 360 } else { 361 return "GenerateLightStateUsingMessage(" + msg + ")"; 362 } 363 } else if (arg.predefined_type() == "GpsCallbacks*") { 364 return "GenerateGpsCallbacks()"; 365 } else if (arg.predefined_type() == "GpsUtcTime") { 366 return "GenerateGpsUtcTime()"; 367 } else if (arg.predefined_type() == "vts_gps_latitude") { 368 return "GenerateLatitude()"; 369 } else if (arg.predefined_type() == "vts_gps_longitude") { 370 return "GenerateLongitude()"; 371 } else if (arg.predefined_type() == "vts_gps_accuracy") { 372 return "GenerateGpsAccuracy()"; 373 } else if (arg.predefined_type() == "vts_gps_flags_uint16") { 374 return "GenerateGpsFlagsUint16()"; 375 } else if (arg.predefined_type() == "GpsPositionMode") { 376 return "GenerateGpsPositionMode()"; 377 } else if (arg.predefined_type() == "GpsPositionRecurrence") { 378 return "GenerateGpsPositionRecurrence()"; 379 } else if (arg.predefined_type() == "hw_module_t*") { 380 return "(hw_module_t*) malloc(sizeof(hw_module_t))"; 381 } else if (arg.predefined_type() == "hw_module_t**") { 382 return "(hw_module_t**) malloc(sizeof(hw_module_t*))"; 383 } else if (arg.predefined_type() == "hw_device_t**") { 384 return "(hw_device_t**) malloc(sizeof(hw_device_t*))"; 385 } else if (arg.predefined_type() == "camera_info_t*") { 386 if (msg.length() == 0) { 387 return "GenerateCameraInfo()"; 388 } else { 389 return "GenerateCameraInfoUsingMessage(" + msg + ")"; 390 } 391 } else if (arg.predefined_type() == "camera_module_callbacks_t*") { 392 return "GenerateCameraModuleCallbacks()"; 393 } else if (arg.predefined_type() == "camera_notify_callback") { 394 return "GenerateCameraNotifyCallback()"; 395 } else if (arg.predefined_type() == "camera_data_callback") { 396 return "GenerateCameraDataCallback()"; 397 } else if (arg.predefined_type() == "camera_data_timestamp_callback") { 398 return "GenerateCameraDataTimestampCallback()"; 399 } else if (arg.predefined_type() == "camera_request_memory") { 400 return "GenerateCameraRequestMemory()"; 401 } else if (arg.predefined_type() == "wifi_handle*") { 402 return "(wifi_handle*) malloc(sizeof(wifi_handle))"; 403 } else if (arg.predefined_type() == "struct camera_device*") { 404 return "(struct camera_device*) malloc(sizeof(struct camera_device))"; 405 } else if (arg.predefined_type() == "struct preview_stream_ops*") { 406 return "(preview_stream_ops*) malloc(sizeof(preview_stream_ops))"; 407 } else if (endsWith(arg.predefined_type(), "*")) { 408 // known use cases: bt_callbacks_t 409 return "(" + arg.predefined_type() + ") malloc(sizeof(" 410 + arg.predefined_type().substr(0, arg.predefined_type().size() - 1) 411 + "))"; 412 } else { 413 cerr << __func__ << ":" << __LINE__ << " " 414 << "error: unknown instance type " << arg.predefined_type() << endl; 415 } 416 break; 417 } 418 case TYPE_SCALAR: { 419 if (arg.scalar_type() == "bool_t") { 420 return "RandomBool()"; 421 } else if (arg.scalar_type() == "uint32_t") { 422 return "RandomUint32()"; 423 } else if (arg.scalar_type() == "int32_t") { 424 return "RandomInt32()"; 425 } else if (arg.scalar_type() == "uint64_t") { 426 return "RandomUint64()"; 427 } else if (arg.scalar_type() == "int64_t") { 428 return "RandomInt64()"; 429 } else if (arg.scalar_type() == "uint16_t") { 430 return "RandomUint16()"; 431 } else if (arg.scalar_type() == "int16_t") { 432 return "RandomInt16()"; 433 } else if (arg.scalar_type() == "uint8_t") { 434 return "RandomUint8()"; 435 } else if (arg.scalar_type() == "int8_t") { 436 return "RandomInt8()"; 437 } else if (arg.scalar_type() == "float_t") { 438 return "RandomFloat()"; 439 } else if (arg.scalar_type() == "double_t") { 440 return "RandomDouble()"; 441 } else if (arg.scalar_type() == "char_pointer") { 442 return "RandomCharPointer()"; 443 } else if (arg.scalar_type() == "uchar_pointer") { 444 return "(unsigned char*) RandomCharPointer()"; 445 } else if (arg.scalar_type() == "pointer" || 446 arg.scalar_type() == "void_pointer") { 447 return "RandomVoidPointer()"; 448 } 449 cerr << __FILE__ << ":" << __LINE__ << " " 450 << "error: unsupported scalar data type " << arg.scalar_type() << endl; 451 exit(-1); 452 } 453 case TYPE_ENUM: 454 case TYPE_MASK: { 455 if (!arg.has_enum_value() && arg.has_predefined_type()) { 456 if (!message || message->component_class() != HAL_HIDL) { 457 return "(" + arg.predefined_type() + ") RandomUint32()"; 458 } else { 459 std::string predefined_type_name = arg.predefined_type(); 460 ReplaceSubString(predefined_type_name, "::", "__"); 461 return "Random" + predefined_type_name + "()"; 462 // TODO: generate a function which can dynamically choose the value. 463 /* for (const auto& attribute : message->attribute()) { 464 if (attribute.type() == TYPE_ENUM && 465 attribute.name() == arg.predefined_type()) { 466 // TODO: pick at runtime 467 return message->component_name() + "::" 468 + arg.predefined_type() + "::" 469 + attribute.enum_value().enumerator(0); 470 } 471 } */ 472 } 473 } else { 474 cerr << __func__ 475 << " ENUM either has enum value or doesn't have predefined type" 476 << endl; 477 exit(-1); 478 } 479 break; 480 } 481 case TYPE_STRING: { 482 return "android::hardware::hidl_string(RandomCharPointer())"; 483 } 484 case TYPE_STRUCT: { 485 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) { 486 return message->component_name() + "::" + arg.predefined_type() + "()"; 487 } 488 break; 489 } 490 case TYPE_VECTOR: { // only for HAL_HIDL 491 // TODO: generate code that initializes a local hidl_vec. 492 return ""; 493 } 494 case TYPE_HIDL_CALLBACK: { 495 return arg.predefined_type() + "()"; 496 } 497 default: 498 break; 499 } 500 cerr << __func__ << ": error: unsupported type " << arg.type() << endl; 501 exit(-1); 502 } 503 504 int vts_fs_mkdirs(char* file_path, mode_t mode) { 505 char* p; 506 507 for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) { 508 *p = '\0'; 509 if (mkdir(file_path, mode) == -1) { 510 if (errno != EEXIST) { 511 *p = '/'; 512 return -1; 513 } 514 } 515 *p = '/'; 516 } 517 return 0; 518 } 519 520 string ClearStringWithNameSpaceAccess(const string& str) { 521 string result = str; 522 ReplaceSubString(result, "::", "__"); 523 return result; 524 } 525 526 // Returns a string which joins the given dir_path and file_name. 527 string PathJoin(const char* dir_path, const char* file_name) { 528 string result; 529 if (dir_path) { 530 result = dir_path; 531 if (!file_name) return result; 532 } else if (!file_name) return result; 533 534 if (file_name[0] != '.') { 535 if (result.c_str()[result.length()-1] != '/') { 536 result += "/"; 537 } 538 } 539 result += file_name; 540 return result; 541 } 542 543 // Returns a string which remove given base_path from file_path if included. 544 string RemoveBaseDir(const string& file_path, const string& base_path) { 545 if (strncmp(file_path.c_str(), base_path.c_str(), base_path.length())) { 546 return file_path; 547 } 548 string result; 549 result = &file_path.c_str()[base_path.length()]; 550 if (result.c_str()[0] == '/') { 551 result = &result.c_str()[1]; 552 } 553 return result; 554 } 555 556 string GetPackageName(const ComponentSpecificationMessage& message) { 557 if (!message.package().empty()) { 558 return message.package(); 559 } 560 return ""; 561 } 562 563 string GetPackagePath(const ComponentSpecificationMessage& message) { 564 string package_path = GetPackageName(message); 565 ReplaceSubString(package_path, ".", "/"); 566 return package_path; 567 } 568 569 string GetPackageNamespaceToken(const ComponentSpecificationMessage& message) { 570 string package_token = GetPackageName(message); 571 ReplaceSubString(package_token, ".", "::"); 572 return package_token; 573 } 574 575 string GetVersion(const ComponentSpecificationMessage& message, 576 bool for_macro) { 577 return GetVersionString(message.component_type_version(), for_macro); 578 } 579 580 int GetMajorVersion(const ComponentSpecificationMessage& message) { 581 string version = GetVersion(message); 582 return stoi(version.substr(0, version.find('.'))); 583 } 584 585 int GetMinorVersion(const ComponentSpecificationMessage& message) { 586 string version = GetVersion(message); 587 return stoi(version.substr(version.find('.') + 1)); 588 } 589 590 string GetComponentBaseName(const ComponentSpecificationMessage& message) { 591 if (!message.component_name().empty()) { 592 return (message.component_name() == "types" 593 ? "types" 594 : message.component_name().substr(1)); 595 } else 596 return GetComponentName(message); 597 } 598 599 string GetComponentName(const ComponentSpecificationMessage& message) { 600 if (!message.component_name().empty()) { 601 return message.component_name(); 602 } 603 604 string component_name = message.original_data_structure_name(); 605 while (!component_name.empty() 606 && (std::isspace(component_name.back()) || component_name.back() == '*')) { 607 component_name.pop_back(); 608 } 609 const auto pos = component_name.find_last_of(" "); 610 if (pos != std::string::npos) { 611 component_name = component_name.substr(pos + 1); 612 } 613 return component_name; 614 } 615 616 FQName GetFQName(const ComponentSpecificationMessage& message) { 617 return FQName(message.package(), 618 GetVersionString(message.component_type_version()), 619 GetComponentName(message)); 620 } 621 622 string GetVarString(const string& var_name) { 623 string var_str = var_name; 624 for (size_t i = 0; i < var_name.length(); i++) { 625 if (!isdigit(var_str[i]) && !isalpha(var_str[i])) { 626 var_str[i] = '_'; 627 } 628 } 629 return var_str; 630 } 631 632 } // namespace vts 633 } // namespace android 634