1 /* 2 * Copyright (C) 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 "AST.h" 18 19 #include "Annotation.h" 20 #include "Coordinator.h" 21 #include "Interface.h" 22 #include "Method.h" 23 #include "Scope.h" 24 25 #include <hidl-util/Formatter.h> 26 #include <android-base/logging.h> 27 #include <string> 28 #include <vector> 29 30 namespace android { 31 32 status_t AST::emitVtsTypeDeclarations(Formatter &out) const { 33 std::string ifaceName; 34 if (AST::isInterface(&ifaceName)) { 35 const Interface *iface = mRootScope->getInterface(); 36 status_t status = iface->emitVtsAttributeDeclaration(out); 37 if (status != OK) { 38 return status; 39 } 40 } else { 41 for (const auto &type : mRootScope->getSubTypes()) { 42 // Skip for TypeDef as it is just an alias of a defined type. 43 if (type->isTypeDef()) { 44 continue; 45 } 46 out << "attribute: {\n"; 47 out.indent(); 48 status_t status = type->emitVtsTypeDeclarations(out); 49 if (status != OK) { 50 return status; 51 } 52 out.unindent(); 53 out << "}\n\n"; 54 } 55 } 56 return OK; 57 } 58 59 status_t AST::generateVts(const std::string &outputPath) const { 60 std::string path = outputPath; 61 path.append(mCoordinator->convertPackageRootToPath(mPackage)); 62 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */)); 63 64 std::string ifaceName; 65 std::string baseName; 66 67 bool isInterface = true; 68 if (!AST::isInterface(&ifaceName)) { 69 baseName = "types"; 70 isInterface = false; 71 } else { 72 const Interface *iface = mRootScope->getInterface(); 73 baseName = iface->getBaseName(); 74 } 75 76 path.append(baseName); 77 path.append(".vts"); 78 79 CHECK(Coordinator::MakeParentHierarchy(path)); 80 FILE *file = fopen(path.c_str(), "w"); 81 82 if (file == NULL) { 83 return -errno; 84 } 85 86 Formatter out(file); 87 88 out << "component_class: HAL_HIDL\n"; 89 out << "component_type_version: " << mPackage.version() 90 << "\n"; 91 out << "component_name: \"" 92 << (isInterface ? ifaceName : "types") 93 << "\"\n\n"; 94 95 out << "package: \"" << mPackage.package() << "\"\n\n"; 96 97 // Generate import statement for all imported interface/types. 98 std::set<FQName> allImportedNames; 99 getAllImportedNames(&allImportedNames); 100 for (const auto &name : allImportedNames) { 101 // ignore IBase. 102 if (name != gIBaseFqName) { 103 out << "import: \"" << name.string() << "\"\n"; 104 } 105 } 106 107 out << "\n"; 108 109 if (isInterface) { 110 const Interface *iface = mRootScope->getInterface(); 111 out << "interface: {\n"; 112 out.indent(); 113 114 std::vector<const Interface *> chain = iface->typeChain(); 115 116 // Generate all the attribute declarations first. 117 status_t status = emitVtsTypeDeclarations(out); 118 if (status != OK) { 119 return status; 120 } 121 // Generate all the method declarations. 122 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 123 const Interface *superInterface = *it; 124 status_t status = superInterface->emitVtsMethodDeclaration(out); 125 if (status != OK) { 126 return status; 127 } 128 } 129 130 out.unindent(); 131 out << "}\n"; 132 } else { 133 status_t status = emitVtsTypeDeclarations(out); 134 if (status != OK) { 135 return status; 136 } 137 } 138 return OK; 139 } 140 141 } // namespace android 142