Split 'IFoo' into 'IFoo' and 'IHwFoo'
The traditional binder "IFoo" interface is coupled
very tightly with Binder; it inherits from Binder
objects and implements several Binder-only methods.
We want to abstract away the RPC mechanism as much as we can; therefore,
we want to create a "clean" IFoo interface, which contains just the
methods defined in the HIDL interface. Separately, there's an IHwFoo
interface, which implements IFoo as well as the necessary Binder
methods.
Changes in hidl-gen to support this:
- Generates IHwFoo.h
- Moved (DECLARE|IMPLEMENT)_HW_BINDER macros from IFoo to IHwFoo
- Added REGISTER_AND_GET_SERVICE macros to IFoo
- Removed all hwbinder/ include paths from IFoo
- When passing an interface through a HIDL method, wrap a
BnInterface object around it
- BnFoo's implementation of IFoo calls through the register
interface implementation
- Updated test code
Tests: hidl_test, hidl_java_test, libhwbinder bench, NFC all work.
Bug: 30588200
Change-Id: Ie7ca4eef905f84aebd06bee971b5f6170e169797
diff --git a/generateCpp.cpp b/generateCpp.cpp
index e472245..57ed349 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -49,6 +49,10 @@
}
if (err == OK) {
+ err = generateHwBinderHeader(outputPath);
+ }
+
+ if (err == OK) {
err = generateProxyHeader(outputPath);
}
@@ -158,10 +162,9 @@
}
out << "#include <hidl/HidlSupport.h>\n";
+ out << "#include <hidl/IServiceManager.h>\n";
if (isInterface) {
- out << "#include <hwbinder/IBinder.h>\n";
- out << "#include <hwbinder/IInterface.h>\n";
out << "#include <hwbinder/Status.h>\n";
}
@@ -170,28 +173,27 @@
enterLeaveNamespace(out, true /* enter */);
out << "\n";
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
if (isInterface) {
out << "struct "
- << ifaceName
- << " : public ";
+ << ifaceName;
const Interface *iface = mRootScope->getInterface();
const Interface *superType = iface->superType();
- if (superType != NULL) {
- out << superType->fullName();
+ if (superType == NULL) {
+ out << " : virtual public RefBase";
} else {
- out << "::android::hardware::IInterface";
+ out << " : public "
+ << superType->fullName();
}
out << " {\n";
out.indent();
- // cut off the leading 'I'.
- const std::string baseName = ifaceName.substr(1);
-
- out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
}
status_t err = emitTypeDeclarations(out);
@@ -204,33 +206,7 @@
const Interface *iface = mRootScope->getInterface();
const Interface *superType = iface->superType();
- out << "enum Call {\n";
- out.indent();
-
- bool first = true;
- for (const auto &method : iface->methods()) {
- out << upcase(method->name());
-
- if (first) {
- out << " = ";
- if (superType != NULL) {
- out << superType->fullName()
- << "::Call::CallCount";
- } else {
- out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
- }
-
- first = false;
- }
-
- out << ",\n";
- }
-
- out << "CallCount\n";
-
- out.unindent();
- out << "};\n\n";
-
+ out << "virtual bool isRemote() const { return false; } \n\n";
bool haveCallbacks = false;
for (const auto &method : iface->methods()) {
const bool returnsValue = !method->results().empty();
@@ -284,6 +260,8 @@
out << ") = 0;\n";
}
+
+ out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
}
if (isInterface) {
@@ -300,12 +278,143 @@
return OK;
}
+status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
+ std::string ifaceName;
+ if(!AST::isInterface(&ifaceName)) {
+ // types.hal does not get an HwBinder header.
+ return OK;
+ }
+
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
+ const std::string klassName = "IHw" + baseName;
+
+ std::string path = outputPath;
+ path.append(mCoordinator->convertPackageRootToPath(mPackage));
+ path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
+ path.append(klassName + ".h");
+
+ FILE* file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ const std::string guard = makeHeaderGuard(klassName);
+
+ out << "#ifndef " << guard << "\n";
+ out << "#define " << guard << "\n\n";
+
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, false /* cpp_compatible */);
+
+ out << "#include <";
+ for (const auto &component : packageComponents) {
+ out << component << "/";
+ }
+ out << ifaceName << ".h>\n\n";
+
+ for (const auto &item : mImportedNames) {
+ if (item.name() == "types") {
+ continue;
+ }
+
+ out << "#include <";
+
+ std::vector<std::string> components;
+ item.getPackageAndVersionComponents(
+ &components, false /* cpp_compatible */);
+
+ for (const auto &component : components) {
+ out << component << "/";
+ }
+
+ // cut off the leading I
+ const std::string itemBaseName = item.name().substr(1);
+
+ out << "Bn"
+ << itemBaseName
+ << ".h>\n";
+ }
+
+ out << "\n";
+
+ out << "#include <hidl/HidlSupport.h>\n";
+ out << "#include <hwbinder/IBinder.h>\n";
+ out << "#include <hwbinder/IInterface.h>\n";
+ out << "#include <hwbinder/Status.h>\n";
+
+ out << "\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ out << "struct "
+ << klassName
+ << " : public "
+ << ifaceName;
+
+ const Interface *iface = mRootScope->getInterface();
+ const Interface *superType = iface->superType();
+
+ out << ", public ::android::hardware::IInterface";
+
+ out << " {\n";
+
+ out.indent();
+
+ out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
+
+ out << "enum Call {\n";
+ out.indent();
+
+ bool first = true;
+ for (const auto &method : iface->methods()) {
+ out << upcase(method->name());
+
+ if (first) {
+ out << " = ";
+ if (superType != NULL) {
+ out << superType->fqName().cppNamespace()
+ << "::IHw"
+ << superType->getBaseName()
+ << "::Call::CallCount";
+ } else {
+ out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
+ }
+
+ first = false;
+ }
+
+ out << ",\n";
+ }
+
+ out << "CallCount\n";
+
+ out.unindent();
+ out << "};\n\n";
+
+ out.unindent();
+
+ out << "};\n\n";
+
+ enterLeaveNamespace(out, false /* enter */);
+
+ out << "\n#endif // " << guard << "\n";
+
+ return OK;
+}
+
status_t AST::emitTypeDeclarations(Formatter &out) const {
return mRootScope->emitTypeDeclarations(out);
}
status_t AST::generateHeaderMethodSignatures(
- Formatter &out, bool abstract) const {
+ Formatter &out, bool stub) const {
const Interface *iface = mRootScope->getInterface();
std::vector<const Interface *> chain;
@@ -322,6 +431,9 @@
<< " follow.\n";
for (const auto &method : superInterface->methods()) {
+ if (stub) {
+ out << "inline ";
+ }
const bool returnsValue = !method->results().empty();
const TypedVar *elidedReturn = method->canElideCallback();
@@ -346,7 +458,33 @@
}
out << ") ";
- out << (abstract ? "= 0" : "override");
+ if (stub) {
+ out << " {\n";
+ out.indent();
+ out << "return mImpl->"
+ << method->name()
+ << "(";
+ bool first = true;
+ for (const auto &arg : method->args()) {
+ if (!first) {
+ out << ", ";
+ }
+ first = false;
+ out << arg->name();
+ }
+ if (returnsValue && elidedReturn == nullptr) {
+ if (!method->args().empty()) {
+ out << ", ";
+ }
+
+ out << "_hidl_cb";
+ }
+ out << ");\n";
+ out.unindent();
+ out << "}";
+ } else {
+ out << "override";
+ }
out << ";\n";
}
@@ -365,12 +503,12 @@
// cut off the leading 'I'.
const std::string baseName = ifaceName.substr(1);
+ const std::string klassName = "Bn" + baseName;
std::string path = outputPath;
path.append(mCoordinator->convertPackageRootToPath(mPackage));
path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
- path.append("Bn");
- path.append(baseName);
+ path.append(klassName);
path.append(".h");
CHECK(Coordinator::MakeParentHierarchy(path));
@@ -382,7 +520,7 @@
Formatter out(file);
- const std::string guard = makeHeaderGuard("Bn" + baseName);
+ const std::string guard = makeHeaderGuard(klassName);
out << "#ifndef " << guard << "\n";
out << "#define " << guard << "\n\n";
@@ -395,7 +533,7 @@
for (const auto &component : packageComponents) {
out << component << "/";
}
- out << ifaceName << ".h>\n\n";
+ out << "IHw" << baseName << ".h>\n\n";
enterLeaveNamespace(out, true /* enter */);
out << "\n";
@@ -403,12 +541,15 @@
out << "struct "
<< "Bn"
<< baseName
- << " : public ::android::hardware::BnInterface<"
- << ifaceName
+ << " : public ::android::hardware::BnInterface<I"
+ << baseName << ", IHw" << baseName
<< "> {\n";
out.indent();
-
+ out << "explicit Bn"
+ << baseName
+ << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
+ << "\n\n";
out << "::android::status_t onTransact(\n";
out.indent();
out.indent();
@@ -420,8 +561,7 @@
out.unindent();
out.unindent();
- generateHeaderMethodSignatures(out, true); // = 0
-
+ generateHeaderMethodSignatures(out, true); // stub
out.unindent();
out << "};\n\n";
@@ -472,7 +612,7 @@
for (const auto &component : packageComponents) {
out << component << "/";
}
- out << ifaceName << ".h>\n\n";
+ out << "IHw" << baseName << ".h>\n\n";
enterLeaveNamespace(out, true /* enter */);
out << "\n";
@@ -480,8 +620,8 @@
out << "struct "
<< "Bp"
<< baseName
- << " : public ::android::hardware::BpInterface<"
- << ifaceName
+ << " : public ::android::hardware::BpInterface<IHw"
+ << baseName
<< "> {\n";
out.indent();
@@ -491,7 +631,9 @@
<< "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
<< "\n\n";
- generateHeaderMethodSignatures(out, false); // override
+ out << "virtual bool isRemote() const { return true; } \n\n";
+
+ generateHeaderMethodSignatures(out, false); // proxy
out.unindent();
@@ -570,6 +712,10 @@
err = generateStubSource(out, baseName);
}
+ if (err == OK && isInterface) {
+ out << "IMPLEMENT_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
+ }
+
enterLeaveNamespace(out, false /* enter */);
return err;
@@ -631,7 +777,7 @@
out.indent();
out << ": BpInterface"
- << "<I"
+ << "<IHw"
<< baseName
<< ">(_hidl_impl) {\n";
@@ -684,12 +830,13 @@
out << "::android::hardware::Parcel _hidl_reply;\n";
out << "::android::status_t _hidl_err;\n";
out << "::android::hardware::Status _hidl_status;\n\n";
-
declareCppReaderLocals(out, method->results());
out << "_hidl_err = _hidl_data.writeInterfaceToken("
- << superInterface->fullName()
- << "::getInterfaceDescriptor());\n";
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
+ << "::descriptor);\n";
out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
@@ -703,9 +850,11 @@
Type::ErrorMode_Goto);
}
- out << "_hidl_err = remote()->transact(I"
- << baseName
- << "::"
+ out << "_hidl_err = remote()->transact("
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
+ << "::Call::"
<< upcase(method->name())
<< ", _hidl_data, &_hidl_reply";
if (method->isOneway()) {
@@ -798,6 +947,25 @@
const std::string klassName = "Bn" + baseName;
+ out << klassName
+ << "::"
+ << klassName
+ << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
+
+ out.indent();
+ out.indent();
+
+ out << ": BnInterface"
+ << "<I"
+ << baseName
+ << ", IHw"
+ << baseName
+ << ">(_hidl_impl) {\n";
+
+ out.unindent();
+ out.unindent();
+ out << "}\n\n";
+
out << "::android::status_t " << klassName << "::onTransact(\n";
out.indent();
@@ -812,7 +980,6 @@
out.unindent();
out << "::android::status_t _hidl_err = ::android::OK;\n\n";
-
out << "switch (_hidl_code) {\n";
out.indent();
@@ -829,7 +996,9 @@
for (const auto &method : superInterface->methods()) {
out << "case "
- << superInterface->fullName()
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
<< "::Call::"
<< upcase(method->name())
<< ":\n{\n";
@@ -852,7 +1021,7 @@
out.indent();
out << "return ::android::hardware::BnInterface<I"
- << baseName
+ << baseName << ", IHw" << baseName
<< ">::onTransact(\n";
out.indent();
@@ -898,8 +1067,10 @@
status_t AST::generateStubSourceForMethod(
Formatter &out, const Interface *iface, const Method *method) const {
out << "if (!_hidl_data.enforceInterface("
- << iface->fullName()
- << "::getInterfaceDescriptor())) {\n";
+ << iface->fqName().cppNamespace()
+ << "::IHw"
+ << iface->getBaseName()
+ << "::descriptor)) {\n";
out.indent();
out << "_hidl_err = ::android::BAD_TYPE;\n";