1 /* 2 * Copyright (C) 2017 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 "Coordinator.h" 20 #include "EnumType.h" 21 #include "HidlTypeAssertion.h" 22 #include "Interface.h" 23 #include "Method.h" 24 #include "Reference.h" 25 #include "ScalarType.h" 26 #include "Scope.h" 27 28 #include <android-base/logging.h> 29 #include <hidl-util/Formatter.h> 30 #include <hidl-util/StringHelper.h> 31 #include <algorithm> 32 #include <string> 33 #include <vector> 34 35 namespace android { 36 37 void AST::generateCppAdapterHeader(Formatter& out) const { 38 const std::string klassName = AST::isInterface() ? getInterface()->getAdapterName() : "Atypes"; 39 const std::string guard = makeHeaderGuard(klassName, true /* indicateGenerated */); 40 41 out << "#ifndef " << guard << "\n"; 42 out << "#define " << guard << "\n\n"; 43 44 if (AST::isInterface()) { 45 generateCppPackageInclude(out, mPackage, getInterface()->definedName()); 46 47 enterLeaveNamespace(out, true /* enter */); 48 out.endl(); 49 50 const std::string mockName = getInterface()->fqName().cppName(); 51 52 out << "class " << klassName << " : public " << mockName << " "; 53 out.block([&] { 54 out << "public:\n"; 55 out << "typedef " << mockName << " Pure;\n"; 56 57 out << klassName << "(const ::android::sp<" << mockName << ">& impl);\n"; 58 59 generateMethods(out, [&](const Method* method, const Interface* /* interface */) { 60 if (method->isHidlReserved()) { 61 return; 62 } 63 64 out << "virtual "; 65 method->generateCppSignature(out); 66 out << " override;\n"; 67 }); 68 out << "private:\n"; 69 out << "::android::sp<" << mockName << "> mImpl;\n"; 70 71 }) << ";\n\n"; 72 73 enterLeaveNamespace(out, false /* enter */); 74 } else { 75 out << "// no adapters for types.hal\n"; 76 } 77 78 out << "#endif // " << guard << "\n"; 79 } 80 81 void AST::generateCppAdapterSource(Formatter& out) const { 82 const std::string klassName = AST::isInterface() ? getInterface()->getAdapterName() : "Atypes"; 83 84 generateCppPackageInclude(out, mPackage, klassName); 85 86 if (AST::isInterface()) { 87 out << "#include <hidladapter/HidlBinderAdapter.h>\n"; 88 generateCppPackageInclude(out, mPackage, getInterface()->definedName()); 89 90 std::set<FQName> allImportedNames; 91 getAllImportedNames(&allImportedNames); 92 for (const auto& item : allImportedNames) { 93 if (item.name() == "types") { 94 continue; 95 } 96 generateCppPackageInclude(out, item, item.getInterfaceAdapterName()); 97 } 98 99 out.endl(); 100 101 enterLeaveNamespace(out, true /* enter */); 102 out.endl(); 103 104 const std::string mockName = getInterface()->fqName().cppName(); 105 106 out << klassName << "::" << klassName << "(const ::android::sp<" << mockName 107 << ">& impl) : mImpl(impl) {}"; 108 109 generateMethods(out, [&](const Method* method, const Interface* /* interface */) { 110 generateAdapterMethod(out, method); 111 }); 112 113 enterLeaveNamespace(out, false /* enter */); 114 out.endl(); 115 } else { 116 out << "// no adapters for types.hal\n"; 117 } 118 } 119 120 void AST::generateAdapterMethod(Formatter& out, const Method* method) const { 121 if (method->isHidlReserved()) { 122 return; 123 } 124 125 const auto adapt = [](Formatter& out, const std::string& var, const Type* type) { 126 if (!type->isInterface()) { 127 out << var; 128 return; 129 } 130 131 const Interface* interface = static_cast<const Interface*>(type); 132 out << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>(" 133 << interface->fqName().cppName() << "::castFrom(" 134 << "::android::hardware::details::adaptWithDefault(" 135 << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>(" << var 136 << "), [&] { return new " << interface->fqName().getInterfaceAdapterFqName().cppName() 137 << "(" << var << "); })))"; 138 }; 139 140 const std::string klassName = getInterface()->getAdapterName(); 141 142 method->generateCppSignature(out, klassName); 143 out.block([&] { 144 bool hasCallback = !method->canElideCallback() && !method->results().empty(); 145 146 if (hasCallback) { 147 out << method->name() << "_cb _hidl_cb_wrapped = [&]("; 148 method->emitCppResultSignature(out); 149 out << ") "; 150 out.block([&] { 151 out << "return _hidl_cb(\n"; 152 out.indent([&]() { 153 out.join(method->results().begin(), method->results().end(), ",\n", 154 [&](auto arg) { adapt(out, arg->name(), arg->get()); }); 155 }); 156 out << ");\n"; 157 }); 158 out << ";\n"; 159 } 160 161 out << "auto _hidl_out = mImpl->" << method->name() << "(\n"; 162 out.indent([&]() { 163 out.join(method->args().begin(), method->args().end(), ",\n", 164 [&](auto arg) { adapt(out, arg->name(), arg->get()); }); 165 if (hasCallback) { 166 if (!method->args().empty()) { 167 out << ",\n"; 168 } 169 out << "_hidl_cb_wrapped"; 170 } 171 }); 172 out << ");\n"; 173 174 const auto elidedCallback = method->canElideCallback(); 175 if (elidedCallback) { 176 out.sIf("!_hidl_out.isOkUnchecked()", [&] { out << "return _hidl_out;\n"; }); 177 out << "return "; 178 adapt(out, "_hidl_out", elidedCallback->get()); 179 out << ";\n"; 180 } else { 181 out << "return _hidl_out;\n"; 182 } 183 }).endl(); 184 } 185 186 } // namespace android 187