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 const ComponentSpecificationMessage* message, 158 bool generate_const, 159 int var_depth) { 160 string result; 161 switch (arg.type()) { 162 case TYPE_VOID: 163 { 164 return "void"; 165 } 166 case TYPE_PREDEFINED: 167 { 168 result = arg.predefined_type(); 169 break; 170 } 171 case TYPE_SCALAR: 172 { 173 result = GetCppVariableType(arg.scalar_type()); 174 break; 175 } 176 case TYPE_STRING: 177 { 178 result = "::android::hardware::hidl_string"; 179 break; 180 } 181 case TYPE_ENUM: 182 { 183 if (!arg.has_enum_value() && arg.has_predefined_type()) { 184 result = arg.predefined_type(); 185 } else if (arg.has_enum_value() && arg.has_name()) { 186 result = arg.name(); // nested enum type. 187 } else { 188 cerr << __func__ << ":" << __LINE__ 189 << " ERROR no predefined_type set for enum variable" << endl; 190 exit(-1); 191 } 192 break; 193 } 194 case TYPE_VECTOR: 195 { 196 string element_type = GetCppVariableType(arg.vector_value(0), message); 197 if (generate_const && arg.vector_value(0).type() == TYPE_REF) { 198 result = "::android::hardware::hidl_vec<const " + element_type + ">"; 199 } else { 200 result = "::android::hardware::hidl_vec<" + element_type + ">"; 201 } 202 break; 203 } 204 case TYPE_ARRAY: 205 { 206 string element_type; 207 if (arg.vector_value(0).type() != TYPE_ARRAY) { 208 element_type = GetCppVariableType(arg.vector_value(0), message); 209 result = "::android::hardware::hidl_array<" + element_type + "," 210 + to_string(arg.vector_size()) + ">"; 211 } else { 212 element_type = GetCppVariableType(arg.vector_value(0), message); 213 string prefix = element_type.substr(0, element_type.find(",") + 1); 214 string suffix = element_type.substr(element_type.find(",")); 215 result = prefix + " " + to_string(arg.vector_size()) + suffix; 216 } 217 break; 218 } 219 case TYPE_STRUCT: 220 { 221 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) { 222 result = arg.predefined_type(); 223 } else if (arg.has_struct_type()) { 224 result = arg.struct_type(); 225 } else if (arg.sub_struct_size() > 0 || arg.struct_value_size() > 0) { 226 result = arg.name(); 227 } else { 228 cerr << __func__ << ":" << __LINE__ << " ERROR" 229 << " no predefined_type, struct_type, nor sub_struct set" 230 << " for struct variable" 231 << " (arg name " << arg.name() << ")" << endl; 232 exit(-1); 233 } 234 break; 235 } 236 case TYPE_UNION: 237 { 238 if (arg.union_value_size() == 0 && arg.has_predefined_type()) { 239 result = arg.predefined_type(); 240 } else if (arg.has_union_type()) { 241 result = arg.union_type(); 242 } else { 243 cerr << __func__ << ":" << __LINE__ 244 << " ERROR no predefined_type or union_type set for union" 245 << " variable" << endl; 246 exit(-1); 247 } 248 break; 249 } 250 case TYPE_HIDL_CALLBACK: 251 { 252 if (arg.has_predefined_type()) { 253 result = "sp<" + arg.predefined_type() + ">"; 254 } else { 255 cerr << __func__ << ":" << __LINE__ 256 << " ERROR no predefined_type set for hidl callback variable" 257 << endl; 258 exit(-1); 259 } 260 break; 261 } 262 case TYPE_HANDLE: 263 { 264 result = "::android::hardware::hidl_handle"; 265 break; 266 } 267 case TYPE_HIDL_INTERFACE: 268 { 269 if (arg.has_predefined_type()) { 270 result = "sp<" + arg.predefined_type() + ">"; 271 } else { 272 cerr << __func__ << ":" << __LINE__ 273 << " ERROR no predefined_type set for hidl interface variable" 274 << endl; 275 exit(-1); 276 } 277 break; 278 } 279 case TYPE_MASK: 280 { 281 result = GetCppVariableType(arg.scalar_type()); 282 break; 283 } 284 case TYPE_HIDL_MEMORY: 285 { 286 result = "::android::hardware::hidl_memory"; 287 break; 288 } 289 case TYPE_POINTER: 290 { 291 result = "void*"; 292 if (generate_const) { 293 return "const " + result; 294 } 295 return result; 296 } 297 case TYPE_FMQ_SYNC: 298 { 299 string element_type = GetCppVariableType(arg.fmq_value(0), message); 300 result = "::android::hardware::MQDescriptorSync<" + element_type + ">"; 301 break; 302 } 303 case TYPE_FMQ_UNSYNC: 304 { 305 string element_type = GetCppVariableType(arg.fmq_value(0), message); 306 result = "::android::hardware::MQDescriptorUnsync<" + element_type + ">"; 307 break; 308 } 309 case TYPE_REF: 310 { 311 string element_type = GetCppVariableType(arg.ref_value(), message, 312 false, var_depth + 1); 313 if (element_type.length() > 0) { 314 if (var_depth == 0) { 315 return "const " + element_type + " *"; 316 } else { 317 return element_type + " *const"; 318 } 319 } 320 cerr << __func__ << ":" << __LINE__ << " ERROR" 321 << " TYPE_REF malformed" << endl; 322 exit(-1); 323 } 324 default: 325 { 326 cerr << __func__ << ":" << __LINE__ << " " << ": type " << arg.type() 327 << " not supported" << endl; 328 exit(-1); 329 } 330 } 331 if (generate_const) { 332 return "const " + result + "&"; 333 } 334 return result; 335 } 336 337 string GetConversionToProtobufFunctionName(VariableSpecificationMessage arg) { 338 if (arg.type() == TYPE_PREDEFINED) { 339 if (arg.predefined_type() == "camera_info_t*") { 340 return "ConvertCameraInfoToProtobuf"; 341 } else if (arg.predefined_type() == "hw_device_t**") { 342 return ""; 343 } else { 344 cerr << __FILE__ << ":" << __LINE__ << " " 345 << "error: unknown instance type " << arg.predefined_type() << endl; 346 } 347 } 348 cerr << __FUNCTION__ << ": non-supported type " << arg.type() << endl; 349 exit(-1); 350 } 351 352 string GetCppInstanceType( 353 const VariableSpecificationMessage& arg, 354 const string& msg, 355 const ComponentSpecificationMessage* message) { 356 switch(arg.type()) { 357 case TYPE_PREDEFINED: { 358 if (arg.predefined_type() == "struct light_state_t*") { 359 if (msg.length() == 0) { 360 return "GenerateLightState()"; 361 } else { 362 return "GenerateLightStateUsingMessage(" + msg + ")"; 363 } 364 } else if (arg.predefined_type() == "GpsCallbacks*") { 365 return "GenerateGpsCallbacks()"; 366 } else if (arg.predefined_type() == "GpsUtcTime") { 367 return "GenerateGpsUtcTime()"; 368 } else if (arg.predefined_type() == "vts_gps_latitude") { 369 return "GenerateLatitude()"; 370 } else if (arg.predefined_type() == "vts_gps_longitude") { 371 return "GenerateLongitude()"; 372 } else if (arg.predefined_type() == "vts_gps_accuracy") { 373 return "GenerateGpsAccuracy()"; 374 } else if (arg.predefined_type() == "vts_gps_flags_uint16") { 375 return "GenerateGpsFlagsUint16()"; 376 } else if (arg.predefined_type() == "GpsPositionMode") { 377 return "GenerateGpsPositionMode()"; 378 } else if (arg.predefined_type() == "GpsPositionRecurrence") { 379 return "GenerateGpsPositionRecurrence()"; 380 } else if (arg.predefined_type() == "hw_module_t*") { 381 return "(hw_module_t*) malloc(sizeof(hw_module_t))"; 382 } else if (arg.predefined_type() == "hw_module_t**") { 383 return "(hw_module_t**) malloc(sizeof(hw_module_t*))"; 384 } else if (arg.predefined_type() == "hw_device_t**") { 385 return "(hw_device_t**) malloc(sizeof(hw_device_t*))"; 386 } else if (arg.predefined_type() == "camera_info_t*") { 387 if (msg.length() == 0) { 388 return "GenerateCameraInfo()"; 389 } else { 390 return "GenerateCameraInfoUsingMessage(" + msg + ")"; 391 } 392 } else if (arg.predefined_type() == "camera_module_callbacks_t*") { 393 return "GenerateCameraModuleCallbacks()"; 394 } else if (arg.predefined_type() == "camera_notify_callback") { 395 return "GenerateCameraNotifyCallback()"; 396 } else if (arg.predefined_type() == "camera_data_callback") { 397 return "GenerateCameraDataCallback()"; 398 } else if (arg.predefined_type() == "camera_data_timestamp_callback") { 399 return "GenerateCameraDataTimestampCallback()"; 400 } else if (arg.predefined_type() == "camera_request_memory") { 401 return "GenerateCameraRequestMemory()"; 402 } else if (arg.predefined_type() == "wifi_handle*") { 403 return "(wifi_handle*) malloc(sizeof(wifi_handle))"; 404 } else if (arg.predefined_type() == "struct camera_device*") { 405 return "(struct camera_device*) malloc(sizeof(struct camera_device))"; 406 } else if (arg.predefined_type() == "struct preview_stream_ops*") { 407 return "(preview_stream_ops*) malloc(sizeof(preview_stream_ops))"; 408 } else if (endsWith(arg.predefined_type(), "*")) { 409 // known use cases: bt_callbacks_t 410 return "(" + arg.predefined_type() + ") malloc(sizeof(" 411 + arg.predefined_type().substr(0, arg.predefined_type().size() - 1) 412 + "))"; 413 } else { 414 cerr << __func__ << ":" << __LINE__ << " " 415 << "error: unknown instance type " << arg.predefined_type() << endl; 416 } 417 break; 418 } 419 case TYPE_SCALAR: { 420 if (arg.scalar_type() == "bool_t") { 421 return "RandomBool()"; 422 } else if (arg.scalar_type() == "uint32_t") { 423 return "RandomUint32()"; 424 } else if (arg.scalar_type() == "int32_t") { 425 return "RandomInt32()"; 426 } else if (arg.scalar_type() == "uint64_t") { 427 return "RandomUint64()"; 428 } else if (arg.scalar_type() == "int64_t") { 429 return "RandomInt64()"; 430 } else if (arg.scalar_type() == "uint16_t") { 431 return "RandomUint16()"; 432 } else if (arg.scalar_type() == "int16_t") { 433 return "RandomInt16()"; 434 } else if (arg.scalar_type() == "uint8_t") { 435 return "RandomUint8()"; 436 } else if (arg.scalar_type() == "int8_t") { 437 return "RandomInt8()"; 438 } else if (arg.scalar_type() == "float_t") { 439 return "RandomFloat()"; 440 } else if (arg.scalar_type() == "double_t") { 441 return "RandomDouble()"; 442 } else if (arg.scalar_type() == "char_pointer") { 443 return "RandomCharPointer()"; 444 } else if (arg.scalar_type() == "uchar_pointer") { 445 return "(unsigned char*) RandomCharPointer()"; 446 } else if (arg.scalar_type() == "pointer" || 447 arg.scalar_type() == "void_pointer") { 448 return "RandomVoidPointer()"; 449 } 450 cerr << __FILE__ << ":" << __LINE__ << " " 451 << "error: unsupported scalar data type " << arg.scalar_type() << endl; 452 exit(-1); 453 } 454 case TYPE_ENUM: 455 case TYPE_MASK: { 456 if (!arg.has_enum_value() && arg.has_predefined_type()) { 457 if (!message || message->component_class() != HAL_HIDL) { 458 return "(" + arg.predefined_type() + ") RandomUint32()"; 459 } else { 460 std::string predefined_type_name = arg.predefined_type(); 461 ReplaceSubString(predefined_type_name, "::", "__"); 462 return "Random" + predefined_type_name + "()"; 463 // TODO: generate a function which can dynamically choose the value. 464 /* for (const auto& attribute : message->attribute()) { 465 if (attribute.type() == TYPE_ENUM && 466 attribute.name() == arg.predefined_type()) { 467 // TODO: pick at runtime 468 return message->component_name() + "::" 469 + arg.predefined_type() + "::" 470 + attribute.enum_value().enumerator(0); 471 } 472 } */ 473 } 474 } else { 475 cerr << __func__ 476 << " ENUM either has enum value or doesn't have predefined type" 477 << endl; 478 exit(-1); 479 } 480 break; 481 } 482 case TYPE_STRING: { 483 return "android::hardware::hidl_string(RandomCharPointer())"; 484 } 485 case TYPE_STRUCT: { 486 if (arg.struct_value_size() == 0 && arg.has_predefined_type()) { 487 return message->component_name() + "::" + arg.predefined_type() + "()"; 488 } 489 break; 490 } 491 case TYPE_VECTOR: { // only for HAL_HIDL 492 // TODO: generate code that initializes a local hidl_vec. 493 return ""; 494 } 495 case TYPE_HIDL_CALLBACK: { 496 return arg.predefined_type() + "()"; 497 } 498 default: 499 break; 500 } 501 cerr << __func__ << ": error: unsupported type " << arg.type() << endl; 502 exit(-1); 503 } 504 505 int vts_fs_mkdirs(char* file_path, mode_t mode) { 506 char* p; 507 508 for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) { 509 *p = '\0'; 510 if (mkdir(file_path, mode) == -1) { 511 if (errno != EEXIST) { 512 *p = '/'; 513 return -1; 514 } 515 } 516 *p = '/'; 517 } 518 return 0; 519 } 520 521 string ClearStringWithNameSpaceAccess(const string& str) { 522 string result = str; 523 ReplaceSubString(result, "::", "__"); 524 return result; 525 } 526 527 // Returns a string which joins the given dir_path and file_name. 528 string PathJoin(const char* dir_path, const char* file_name) { 529 string result; 530 if (dir_path) { 531 result = dir_path; 532 if (!file_name) return result; 533 } else if (!file_name) return result; 534 535 if (file_name[0] != '.') { 536 if (result.c_str()[result.length()-1] != '/') { 537 result += "/"; 538 } 539 } 540 result += file_name; 541 return result; 542 } 543 544 // Returns a string which remove given base_path from file_path if included. 545 string RemoveBaseDir(const string& file_path, const string& base_path) { 546 if (strncmp(file_path.c_str(), base_path.c_str(), base_path.length())) { 547 return file_path; 548 } 549 string result; 550 result = &file_path.c_str()[base_path.length()]; 551 if (result.c_str()[0] == '/') { 552 result = &result.c_str()[1]; 553 } 554 return result; 555 } 556 557 string GetPackageName(const ComponentSpecificationMessage& message) { 558 if (!message.package().empty()) { 559 return message.package(); 560 } 561 return ""; 562 } 563 564 string GetPackagePath(const ComponentSpecificationMessage& message) { 565 string package_path = GetPackageName(message); 566 ReplaceSubString(package_path, ".", "/"); 567 return package_path; 568 } 569 570 string GetPackageNamespaceToken(const ComponentSpecificationMessage& message) { 571 string package_token = GetPackageName(message); 572 ReplaceSubString(package_token, ".", "::"); 573 return package_token; 574 } 575 576 string GetVersion(const ComponentSpecificationMessage& message, 577 bool for_macro) { 578 return GetVersionString(message.component_type_version(), for_macro); 579 } 580 581 string GetComponentBaseName(const ComponentSpecificationMessage& message) { 582 if (!message.component_name().empty()) { 583 return (message.component_name() == "types" 584 ? "types" 585 : message.component_name().substr(1)); 586 } else 587 return GetComponentName(message); 588 } 589 590 string GetComponentName(const ComponentSpecificationMessage& message) { 591 if (!message.component_name().empty()) { 592 return message.component_name(); 593 } 594 595 string component_name = message.original_data_structure_name(); 596 while (!component_name.empty() 597 && (std::isspace(component_name.back()) || component_name.back() == '*')) { 598 component_name.pop_back(); 599 } 600 const auto pos = component_name.find_last_of(" "); 601 if (pos != std::string::npos) { 602 component_name = component_name.substr(pos + 1); 603 } 604 return component_name; 605 } 606 607 FQName GetFQName(const ComponentSpecificationMessage& message) { 608 return FQName(message.package(), 609 GetVersionString(message.component_type_version()), 610 GetComponentName(message)); 611 } 612 613 } // namespace vts 614 } // namespace android 615