IHidlInterfaceBase for all autogenerated interfaces.
Add an interfaceChain() method to each interface
to facilitate casting between interfaces.
Add ::descriptor for each interface (so that
IFoo::descriptor won't fall back to
IHidlInterfaceBase::descriptor.
Test: hidl_test
Test: cd system/tools/hidl && mma
Test: cd hardware/interfaces/test && mma
Bug: 32337854
Change-Id: I317b7905750db0bfefc4c5fd608a07080923c719
diff --git a/Interface.cpp b/Interface.cpp
index 5951f87..09959ae 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -18,51 +18,119 @@
#include "Annotation.h"
#include "Method.h"
+#include "StringType.h"
+#include "VectorType.h"
#include <android-base/logging.h>
#include <hidl-util/Formatter.h>
+#include <hidl-util/StringHelper.h>
#include <iostream>
+#include <sstream>
namespace android {
+/* It is very important that these values NEVER change. These values
+ * must remain unchanged over the lifetime of android. This is
+ * because the framework on a device will be updated independently of
+ * the hals on a device. If the hals are compiled with one set of
+ * transaction values, and the framework with another, then the
+ * interface between them will be destroyed, and the device will not
+ * work.
+ */
+enum {
+ // These values are defined in hardware::IBinder.
+ /////////////////// User defined transactions
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ LAST_CALL_TRANSACTION = 0x00efffff,
+ /////////////////// HIDL reserved
+ FIRST_HIDL_TRANSACTION = 0x00f00000,
+ HIDL_DESCRIPTOR_CHAIN_TRANSACTION = FIRST_HIDL_TRANSACTION,
+ LAST_HIDL_TRANSACTION = 0x00ffffff,
+};
+
Interface::Interface(const char *localName, Interface *super)
: Scope(localName),
mSuperType(super),
mIsJavaCompatibleInProgress(false) {
+ mReservedMethods.push_back(createDescriptorChainMethod());
}
+Method *Interface::createDescriptorChainMethod() const {
+ VectorType *vecType = new VectorType();
+ vecType->setElementType(new StringType());
+ std::vector<TypedVar *> *results = new std::vector<TypedVar *>();
+ results->push_back(new TypedVar("indicator", vecType));
+
+ return new Method("interfaceChain",
+ new std::vector<TypedVar *>() /* args */,
+ results,
+ false /* oneway */,
+ new std::vector<Annotation *>(),
+ HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
+ [this](auto &out) { /* cppImpl */
+ std::vector<const Interface *> chain = typeChain();
+ out << "::android::hardware::hidl_vec<::android::hardware::hidl_string> _hidl_return;\n";
+ out << "_hidl_return.resize(" << chain.size() << ");\n";
+ for (size_t i = 0; i < chain.size(); ++i) {
+ out << "_hidl_return[" << i << "] = \"" << chain[i]->fqName().string() << "\";\n";
+ }
+ out << "_hidl_cb(_hidl_return);\n";
+ out << "return ::android::hardware::Void();";
+ },
+ [this](auto &out) { /* javaImpl */
+ std::vector<const Interface *> chain = typeChain();
+ out << "return new ArrayList<String>(Arrays.asList(\n";
+ out.indent(); out.indent();
+ for (size_t i = 0; i < chain.size(); ++i) {
+ if (i != 0)
+ out << ",\n";
+ out << "\"" << chain[i]->fqName().string() << "\"";
+ }
+ out << "));";
+ out.unindent(); out.unindent();
+ });
+}
+
+
bool Interface::addMethod(Method *method) {
+ CHECK(!method->isHidlReserved());
if (lookupMethod(method->name()) != nullptr) {
LOG(ERROR) << "Redefinition of method " << method->name();
return false;
}
+ size_t serial = FIRST_CALL_TRANSACTION;
- /* It is very important that these values NEVER change. These values
- * must remain unchanged over the lifetime of android. This is
- * because the framework on a device will be updated independently of
- * the hals on a device. If the hals are compiled with one set of
- * transaction values, and the framework with another, then the
- * interface between them will be destroyed, and the device will not
- * work.
- */
- size_t serial = 1; // hardware::IBinder::FIRST_CALL_TRANSACTION;
+ serial += userDefinedMethods().size();
- const Interface *ancestor = this;
+ const Interface *ancestor = mSuperType;
while (ancestor != nullptr) {
- serial += ancestor->methods().size();
+ serial += ancestor->userDefinedMethods().size();
ancestor = ancestor->superType();
}
+ CHECK(serial <= LAST_CALL_TRANSACTION) << "More than "
+ << LAST_CALL_TRANSACTION << " methods are not allowed.";
method->setSerialId(serial);
- mMethods.push_back(method);
+ mUserMethods.push_back(method);
return true;
}
+
const Interface *Interface::superType() const {
return mSuperType;
}
+std::vector<const Interface *> Interface::typeChain() const {
+ std::vector<const Interface *> v;
+ const Interface *iface = this;
+ while (iface != nullptr) {
+ v.push_back(iface);
+ iface = iface->mSuperType;
+ }
+ return v;
+}
+
bool Interface::isInterface() const {
return true;
}
@@ -71,19 +139,41 @@
return true;
}
-const std::vector<Method *> &Interface::methods() const {
- return mMethods;
+const std::vector<Method *> &Interface::userDefinedMethods() const {
+ return mUserMethods;
+}
+
+const std::vector<Method *> &Interface::hidlReservedMethods() const {
+ return mReservedMethods;
+}
+
+std::vector<Method *> Interface::methods() const {
+ std::vector<Method *> v(mUserMethods);
+ v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end());
+ return v;
+}
+
+std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const {
+ std::vector<InterfaceAndMethod> v;
+ std::vector<const Interface *> chain = typeChain();
+ for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+ const Interface *iface = *it;
+ for (Method *userMethod : iface->userDefinedMethods()) {
+ v.push_back(InterfaceAndMethod(iface, userMethod));
+ }
+ }
+ for (Method *reservedMethod : hidlReservedMethods()) {
+ v.push_back(InterfaceAndMethod(this, reservedMethod));
+ }
+ return v;
}
Method *Interface::lookupMethod(std::string name) const {
- const Interface *ancestor = this;
- while (ancestor != nullptr) {
- for (const auto &method : mMethods) {
- if (method->name() == name) {
- return method;
- }
+ for (const auto &tuple : allMethodsFromRoot()) {
+ Method *method = tuple.method();
+ if (method->name() == name) {
+ return method;
}
- ancestor = ancestor->superType();
}
return nullptr;
@@ -228,7 +318,7 @@
}
status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
- for (const auto &method : mMethods) {
+ for (const auto &method : methods()) {
out << "api: {\n";
out.indent();
out << "name: \"" << method->name() << "\"\n";
@@ -297,7 +387,7 @@
bool Interface::hasOnewayMethods() const {
- for (auto const &method : mMethods) {
+ for (auto const &method : methods()) {
if (method->isOneway()) {
return true;
}
@@ -334,7 +424,7 @@
return false;
}
- for (const auto &method : mMethods) {
+ for (const auto &method : methods()) {
if (!method->isJavaCompatible()) {
mIsJavaCompatibleInProgress = false;
return false;
diff --git a/Interface.h b/Interface.h
index 7f7edc7..ae7e032 100644
--- a/Interface.h
+++ b/Interface.h
@@ -19,10 +19,12 @@
#define INTERFACE_H_
#include "Scope.h"
+#include <vector>
namespace android {
struct Method;
+struct InterfaceAndMethod;
struct Interface : public Scope {
Interface(const char *localName, Interface *super);
@@ -34,8 +36,26 @@
const Interface *superType() const;
- const std::vector<Method *> &methods() const;
Method *lookupMethod(std::string name) const;
+ // Super type chain to root type, including myself.
+ // First element is this.
+ std::vector<const Interface *> typeChain() const;
+
+ // user defined methods (explicit definition in HAL files)
+ const std::vector<Method *> &userDefinedMethods() const;
+ // HIDL reserved methods (every interface has these implicitly defined)
+ const std::vector<Method *> &hidlReservedMethods() const;
+ // the sum of userDefinedMethods() and hidlReservedMethods().
+ std::vector<Method *> methods() const;
+
+ // userDefinedMethods() for all super type + methods()
+ // The order will be as follows (in the transaction code order):
+ // great-great-...-great-grand parent->userDefinedMethods()
+ // ...
+ // parent->userDefinedMethods()
+ // this->userDefinedMethods()
+ // this->hidlReservedMethods()
+ std::vector<InterfaceAndMethod> allMethodsFromRoot() const;
std::string getBaseName() const;
@@ -72,12 +92,27 @@
private:
Interface *mSuperType;
- std::vector<Method *> mMethods;
+ std::vector<Method *> mUserMethods;
+ std::vector<Method *> mReservedMethods;
mutable bool mIsJavaCompatibleInProgress;
+ Method *createDescriptorChainMethod() const;
DISALLOW_COPY_AND_ASSIGN(Interface);
};
+// An interface / method tuple.
+struct InterfaceAndMethod {
+ InterfaceAndMethod(const Interface *iface, Method *method)
+ : mInterface(iface),
+ mMethod(method) {}
+ Method *method() const { return mMethod; }
+ const Interface *interface() const { return mInterface; }
+private:
+ // do not own these objects.
+ const Interface *mInterface;
+ Method *mMethod;
+};
+
} // namespace android
#endif // INTERFACE_H_
diff --git a/Method.cpp b/Method.cpp
index 95a688a..dfac662 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -20,6 +20,7 @@
#include "ScalarType.h"
#include "Type.h"
+#include <android-base/logging.h>
#include <hidl-util/Formatter.h>
namespace android {
@@ -36,6 +37,24 @@
mAnnotations(annotations) {
}
+// HIDL reserved methods.
+Method::Method(const char *name,
+ std::vector<TypedVar *> *args,
+ std::vector<TypedVar *> *results,
+ bool oneway,
+ std::vector<Annotation *> *annotations,
+ size_t serial,
+ MethodImpl cppImpl,
+ MethodImpl javaImpl)
+ : Method(name, args, results, oneway, annotations) {
+
+ mIsHidlReserved = true;
+ mSerial = serial;
+ mCppImpl = cppImpl;
+ mJavaImpl = javaImpl;
+}
+
+
std::string Method::name() const {
return mName;
}
@@ -52,7 +71,22 @@
return *mAnnotations;
}
+void Method::cppImpl(Formatter &out) const {
+ CHECK(mIsHidlReserved);
+ if (mCppImpl) {
+ mCppImpl(out);
+ }
+}
+
+void Method::javaImpl(Formatter &out) const {
+ CHECK(mIsHidlReserved);
+ if (mJavaImpl) {
+ mJavaImpl(out);
+ }
+}
+
void Method::setSerialId(size_t serial) {
+ CHECK(!mIsHidlReserved);
mSerial = serial;
}
diff --git a/Method.h b/Method.h
index 3c84914..7e711f0 100644
--- a/Method.h
+++ b/Method.h
@@ -19,6 +19,8 @@
#define METHOD_H_
#include <android-base/macros.h>
+#include <functional>
+#include <hidl-util/Formatter.h>
#include <string>
#include <vector>
@@ -30,17 +32,30 @@
struct Type;
struct TypedVar;
+using MethodImpl = std::function<void(Formatter &)>;
+
struct Method {
Method(const char *name,
std::vector<TypedVar *> *args,
std::vector<TypedVar *> *results,
bool oneway,
std::vector<Annotation *> *annotations);
+ Method(const char *name,
+ std::vector<TypedVar *> *args,
+ std::vector<TypedVar *> *results,
+ bool oneway,
+ std::vector<Annotation *> *annotations,
+ size_t serial,
+ MethodImpl cppImpl,
+ MethodImpl javaImpl);
std::string name() const;
const std::vector<TypedVar *> &args() const;
const std::vector<TypedVar *> &results() const;
bool isOneway() const { return mOneway; }
+ void cppImpl(Formatter &out) const;
+ void javaImpl(Formatter &out) const;
+ bool isHidlReserved() const { return mIsHidlReserved; }
const std::vector<Annotation *> &annotations() const;
void setSerialId(size_t serial);
@@ -68,6 +83,12 @@
bool mOneway;
std::vector<Annotation *> *mAnnotations;
+ bool mIsHidlReserved = false;
+ // The following fields has no meaning if mIsHidlReserved is false.
+ // hard-coded implementation for HIDL reserved methods.
+ MethodImpl mCppImpl = nullptr;
+ MethodImpl mJavaImpl = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(Method);
};
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 2c06990..921d6ae 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -169,7 +169,7 @@
const Interface *superType = iface->superType();
if (superType == NULL) {
- out << " : virtual public RefBase";
+ out << " : virtual public IHidlInterfaceBase";
} else {
out << " : virtual public "
<< superType->fullName();
@@ -199,7 +199,7 @@
out << "return version;\n";
out.unindent();
out << "}\n\n";
- out << "virtual bool isRemote() const { return false; }\n\n";
+ out << "virtual bool isRemote() const override { return false; }\n\n";
bool haveCallbacks = false;
for (const auto &method : iface->methods()) {
const bool returnsValue = !method->results().empty();
@@ -253,9 +253,21 @@
out << method->name() << "_cb _hidl_cb";
}
- out << ") = 0;\n";
+ out << ")";
+ if (method->isHidlReserved()) {
+ out << " override";
+ out << " {\n";
+ out.indent();
+ method->cppImpl(out);
+ out.unindent();
+ out << "\n}\n";
+ } else {
+ out << " = 0;\n";
+ }
}
+ out << "\nstatic const ::android::String16 descriptor;\n\n";
+
out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
}
@@ -504,65 +516,64 @@
const Interface *iface = mRootScope->getInterface();
- std::vector<const Interface *> chain;
- while (iface != NULL) {
- chain.push_back(iface);
- iface = iface->superType();
- }
+ const Interface *prevIterface = nullptr;
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ const Interface *superInterface = tuple.interface();
- for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
- const Interface *superInterface = *it;
-
- out << "// Methods from "
- << superInterface->fullName()
- << " follow.\n";
-
- for (const auto &method : superInterface->methods()) {
- status_t err;
- switch(type) {
- case STUB_HEADER:
- err = generateStubMethod(out,
+ if(prevIterface != superInterface) {
+ if (prevIterface != nullptr) {
+ out << "\n";
+ }
+ out << "// Methods from "
+ << superInterface->fullName()
+ << " follow.\n";
+ prevIterface = superInterface;
+ }
+ status_t err;
+ switch(type) {
+ case STUB_HEADER:
+ err = generateStubMethod(out,
+ className,
+ method,
+ specifyNamespaces);
+ break;
+ case PROXY_HEADER:
+ err = generateProxyDeclaration(out,
+ className,
+ method,
+ specifyNamespaces);
+ break;
+ case IMPL_HEADER:
+ err = generateStubImplDeclaration(out,
+ className,
+ method,
+ specifyNamespaces);
+ break;
+ case IMPL_SOURCE:
+ err = generateStubImplMethod(out,
className,
method,
specifyNamespaces);
- break;
- case PROXY_HEADER:
- err = generateProxyDeclaration(out,
- className,
- method,
- specifyNamespaces);
- break;
- case IMPL_HEADER:
- err = generateStubImplDeclaration(out,
- className,
- method,
- specifyNamespaces);
- break;
- case IMPL_SOURCE:
- err = generateStubImplMethod(out,
- className,
- method,
- specifyNamespaces);
- break;
- case PASSTHROUGH_HEADER:
- err = generatePassthroughMethod(out,
- className,
- method,
- specifyNamespaces);
- break;
- default:
- LOG(ERROR) << "Unkown method type: " << type;
- err = UNKNOWN_ERROR;
- }
-
- if (err != OK) {
- return err;
- }
+ break;
+ case PASSTHROUGH_HEADER:
+ err = generatePassthroughMethod(out,
+ className,
+ method,
+ specifyNamespaces);
+ break;
+ default:
+ LOG(ERROR) << "Unkown method type: " << type;
+ err = UNKNOWN_ERROR;
}
- out << "\n";
+ if (err != OK) {
+ return err;
+ }
}
+ out << "\n";
+
return OK;
}
@@ -711,7 +722,7 @@
<< "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
<< "\n\n";
- out << "virtual bool isRemote() const { return true; }\n\n";
+ out << "virtual bool isRemote() const override { return true; }\n\n";
status_t err = generateMethods(out,
"" /* class name */,
@@ -793,7 +804,16 @@
status_t err = generateTypeSource(out, ifaceName);
if (err == OK && isInterface) {
+ const Interface *iface = mRootScope->getInterface();
out << "constexpr hidl_version " << ifaceName << "::version;\n\n";
+
+ // need to be put here, generateStubSource is using this.
+ out << "const ::android::String16 I"
+ << iface->getBaseName()
+ << "::descriptor(\""
+ << iface->fqName().string()
+ << "\");\n\n";
+
err = generateProxySource(out, baseName);
}
@@ -930,181 +950,178 @@
const Interface *iface = mRootScope->getInterface();
- std::vector<const Interface *> chain;
- while (iface != NULL) {
- chain.push_back(iface);
- iface = iface->superType();
- }
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ const Interface *superInterface = tuple.interface();
+ method->generateCppSignature(out,
+ klassName,
+ true /* specify namespaces */);
- for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
- const Interface *superInterface = *it;
+ const bool returnsValue = !method->results().empty();
+ const TypedVar *elidedReturn = method->canElideCallback();
- for (const auto &method : superInterface->methods()) {
- method->generateCppSignature(out,
- klassName,
- true /* specify namespaces */);
+ out << "{\n";
- const bool returnsValue = !method->results().empty();
- const TypedVar *elidedReturn = method->canElideCallback();
+ out.indent();
- out << "{\n";
+ if (returnsValue && elidedReturn == nullptr) {
+ generateCheckNonNull(out, "_hidl_cb");
+ }
- out.indent();
+ status_t status = generateCppInstrumentationCall(
+ out,
+ InstrumentationEvent::CLIENT_API_ENTRY,
+ superInterface,
+ method);
+ if (status != OK) {
+ return status;
+ }
- if (returnsValue && elidedReturn == nullptr) {
- generateCheckNonNull(out, "_hidl_cb");
+ out << "::android::hardware::Parcel _hidl_data;\n";
+ 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(), true /* forResults */);
+
+ out << "_hidl_err = _hidl_data.writeInterfaceToken(";
+ if (!method->isHidlReserved()) {
+ out << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName();
+ } else {
+ out << "::android::hardware::IHidlInterfaceBase";
+ }
+ out << "::descriptor);\n";
+
+ out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+ // First DFS: write all buffers and resolve pointers for parent
+ for (const auto &arg : method->args()) {
+ emitCppReaderWriter(
+ out,
+ "_hidl_data",
+ false /* parcelObjIsPointer */,
+ arg,
+ false /* reader */,
+ Type::ErrorMode_Goto,
+ false /* addPrefixToName */);
+ }
+
+ // Second DFS: resolve references.
+ for (const auto &arg : method->args()) {
+ emitCppResolveReferences(
+ out,
+ "_hidl_data",
+ false /* parcelObjIsPointer */,
+ arg,
+ false /* reader */,
+ Type::ErrorMode_Goto,
+ false /* addPrefixToName */);
+ }
+
+ out << "_hidl_err = remote()->transact("
+ << method->getSerialId()
+ << " /* "
+ << method->name()
+ << " */, _hidl_data, &_hidl_reply";
+
+ if (method->isOneway()) {
+ out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
+ }
+ out << ");\n";
+
+ out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+ if (!method->isOneway()) {
+ out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
+ out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+ out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
+
+
+ // First DFS: write all buffers and resolve pointers for parent
+ for (const auto &arg : method->results()) {
+ emitCppReaderWriter(
+ out,
+ "_hidl_reply",
+ false /* parcelObjIsPointer */,
+ arg,
+ true /* reader */,
+ Type::ErrorMode_Goto,
+ true /* addPrefixToName */);
}
+ // Second DFS: resolve references.
+ for (const auto &arg : method->results()) {
+ emitCppResolveReferences(
+ out,
+ "_hidl_reply",
+ false /* parcelObjIsPointer */,
+ arg,
+ true /* reader */,
+ Type::ErrorMode_Goto,
+ true /* addPrefixToName */);
+ }
+
+ if (returnsValue && elidedReturn == nullptr) {
+ out << "_hidl_cb(";
+
+ bool first = true;
+ for (const auto &arg : method->results()) {
+ if (!first) {
+ out << ", ";
+ }
+
+ if (arg->type().resultNeedsDeref()) {
+ out << "*";
+ }
+ out << "_hidl_out_" << arg->name();
+
+ first = false;
+ }
+
+ out << ");\n\n";
+ }
status_t status = generateCppInstrumentationCall(
out,
- InstrumentationEvent::CLIENT_API_ENTRY,
+ InstrumentationEvent::CLIENT_API_EXIT,
superInterface,
method);
if (status != OK) {
return status;
}
+ }
- out << "::android::hardware::Parcel _hidl_data;\n";
- 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(), true /* forResults */);
-
- out << "_hidl_err = _hidl_data.writeInterfaceToken("
- << superInterface->fqName().cppNamespace()
- << "::IHw"
- << superInterface->getBaseName()
- << "::descriptor);\n";
-
- out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
- // First DFS: write all buffers and resolve pointers for parent
- for (const auto &arg : method->args()) {
- emitCppReaderWriter(
- out,
- "_hidl_data",
- false /* parcelObjIsPointer */,
- arg,
- false /* reader */,
- Type::ErrorMode_Goto,
- false /* addPrefixToName */);
- }
-
- // Second DFS: resolve references.
- for (const auto &arg : method->args()) {
- emitCppResolveReferences(
- out,
- "_hidl_data",
- false /* parcelObjIsPointer */,
- arg,
- false /* reader */,
- Type::ErrorMode_Goto,
- false /* addPrefixToName */);
- }
-
- out << "_hidl_err = remote()->transact("
- << method->getSerialId()
- << " /* "
- << method->name()
- << " */, _hidl_data, &_hidl_reply";
-
- if (method->isOneway()) {
- out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
- }
- out << ");\n";
-
- out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
- if (!method->isOneway()) {
- out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
- out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
- out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
-
-
- // First DFS: write all buffers and resolve pointers for parent
- for (const auto &arg : method->results()) {
- emitCppReaderWriter(
- out,
- "_hidl_reply",
- false /* parcelObjIsPointer */,
- arg,
- true /* reader */,
- Type::ErrorMode_Goto,
- true /* addPrefixToName */);
- }
-
- // Second DFS: resolve references.
- for (const auto &arg : method->results()) {
- emitCppResolveReferences(
- out,
- "_hidl_reply",
- false /* parcelObjIsPointer */,
- arg,
- true /* reader */,
- Type::ErrorMode_Goto,
- true /* addPrefixToName */);
- }
-
- if (returnsValue && elidedReturn == nullptr) {
- out << "_hidl_cb(";
-
- bool first = true;
- for (const auto &arg : method->results()) {
- if (!first) {
- out << ", ";
- }
-
- if (arg->type().resultNeedsDeref()) {
- out << "*";
- }
- out << "_hidl_out_" << arg->name();
-
- first = false;
- }
-
- out << ");\n\n";
- }
- status_t status = generateCppInstrumentationCall(
- out,
- InstrumentationEvent::CLIENT_API_EXIT,
- superInterface,
- method);
- if (status != OK) {
- return status;
- }
- }
-
- if (elidedReturn != nullptr) {
- std::string extra;
- out << "_hidl_status.setFromStatusT(_hidl_err);\n";
- out << "return ::android::hardware::Return<";
- out << elidedReturn->type().getCppResultType(&extra)
- << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
- } else {
- out << "_hidl_status.setFromStatusT(_hidl_err);\n";
- out << "return ::android::hardware::Return<void>();\n\n";
- }
-
- out.unindent();
- out << "_hidl_error:\n";
- out.indent();
+ if (elidedReturn != nullptr) {
+ std::string extra;
out << "_hidl_status.setFromStatusT(_hidl_err);\n";
out << "return ::android::hardware::Return<";
- if (elidedReturn != nullptr) {
- std::string extra;
- out << method->results().at(0)->type().getCppResultType(&extra);
- } else {
- out << "void";
- }
- out << ">(_hidl_status);\n";
-
- out.unindent();
- out << "}\n\n";
+ out << elidedReturn->type().getCppResultType(&extra)
+ << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
+ } else {
+ out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+ out << "return ::android::hardware::Return<void>();\n\n";
}
+
+ out.unindent();
+ out << "_hidl_error:\n";
+ out.indent();
+ out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+ out << "return ::android::hardware::Return<";
+ if (elidedReturn != nullptr) {
+ std::string extra;
+ out << method->results().at(0)->type().getCppResultType(&extra);
+ } else {
+ out << "void";
+ }
+ out << ">(_hidl_status);\n";
+
+ out.unindent();
+ out << "}\n\n";
}
+
return OK;
}
@@ -1112,11 +1129,11 @@
Formatter &out, const std::string &baseName) const {
out << "IMPLEMENT_HWBINDER_META_INTERFACE("
<< baseName
- << ", \""
- << mPackage.string()
+ << ", "
+ << mPackage.cppNamespace()
<< "::I"
<< baseName
- << "\");\n\n";
+ << "::descriptor);\n\n";
const std::string klassName = "Bn" + baseName;
@@ -1163,34 +1180,26 @@
const Interface *iface = mRootScope->getInterface();
- std::vector<const Interface *> chain;
- while (iface != NULL) {
- chain.push_back(iface);
- iface = iface->superType();
- }
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ const Interface *superInterface = tuple.interface();
+ out << "case "
+ << method->getSerialId()
+ << " /* "
+ << method->name()
+ << " */:\n{\n";
- for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
- const Interface *superInterface = *it;
+ out.indent();
- for (const auto &method : superInterface->methods()) {
- out << "case "
- << method->getSerialId()
- << " /* "
- << method->name()
- << " */:\n{\n";
+ status_t err =
+ generateStubSourceForMethod(out, superInterface, method);
- out.indent();
-
- status_t err =
- generateStubSourceForMethod(out, superInterface, method);
-
- if (err != OK) {
- return err;
- }
-
- out.unindent();
- out << "}\n\n";
+ if (err != OK) {
+ return err;
}
+
+ out.unindent();
+ out << "}\n\n";
}
out << "default:\n{\n";
@@ -1242,11 +1251,17 @@
status_t AST::generateStubSourceForMethod(
Formatter &out, const Interface *iface, const Method *method) const {
- out << "if (!_hidl_data.enforceInterface("
- << iface->fqName().cppNamespace()
- << "::IHw"
- << iface->getBaseName()
- << "::descriptor)) {\n";
+ out << "if (!_hidl_data.enforceInterface(";
+
+ if (!method->isHidlReserved()) {
+ out << iface->fqName().cppNamespace()
+ << "::IHw"
+ << iface->getBaseName();
+ } else {
+ out << "::android::hardware::IHidlInterfaceBase";
+ }
+
+ out << "::descriptor)) {\n";
out.indent();
out << "_hidl_err = ::android::BAD_TYPE;\n";
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 66a35d4..b8b91c4 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -137,27 +137,22 @@
// this is namespace aware code and doesn't require post-processing
out.setNamespace("");
- const Interface *ancestor = iface;
- std::vector<const Interface *> chain;
- while (ancestor != NULL) {
- chain.push_back(ancestor);
- ancestor = ancestor->superType();
- }
+ std::vector<const Interface *> chain = iface->typeChain();
std::set<const FQName> usedTypes{};
for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
const Interface *superInterface = *it;
-
superInterface->addNamedTypesToSet(usedTypes);
+ }
- for (const auto &method : superInterface->methods()) {
- for(const auto & arg : method->args()) {
- arg->type().addNamedTypesToSet(usedTypes);
- }
- for(const auto & results : method->results()) {
- results->type().addNamedTypesToSet(usedTypes);
- }
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ for(const auto & arg : method->args()) {
+ arg->type().addNamedTypesToSet(usedTypes);
+ }
+ for(const auto & results : method->results()) {
+ results->type().addNamedTypesToSet(usedTypes);
}
}
diff --git a/generateJava.cpp b/generateJava.cpp
index 69ce0d1..63643e1 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -304,119 +304,114 @@
out.unindent();
out << "}\n\n";
- std::vector<const Interface *> chain;
- while (iface != NULL) {
- chain.push_back(iface);
- iface = iface->superType();
- }
+ const Interface *prevInterface = nullptr;
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ const Interface *superInterface = tuple.interface();
+ if (prevInterface != superInterface) {
+ out << "// Methods from "
+ << superInterface->fullName()
+ << " follow.\n";
+ prevInterface = superInterface;
+ }
+ const bool returnsValue = !method->results().empty();
+ const bool needsCallback = method->results().size() > 1;
- for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
- const Interface *superInterface = *it;
+ out << "public ";
+ if (returnsValue && !needsCallback) {
+ std::string extra;
+ out << method->results()[0]->type().getJavaType(&extra)
+ << extra;
+ } else {
+ out << "void";
+ }
- out << "// Methods from "
- << superInterface->fullName()
- << " follow.\n";
+ out << " "
+ << method->name()
+ << "("
+ << Method::GetJavaArgSignature(method->args());
- for (const auto &method : superInterface->methods()) {
- const bool returnsValue = !method->results().empty();
- const bool needsCallback = method->results().size() > 1;
-
- out << "public ";
- if (returnsValue && !needsCallback) {
- std::string extra;
- out << method->results()[0]->type().getJavaType(&extra)
- << extra;
- } else {
- out << "void";
+ if (needsCallback) {
+ if (!method->args().empty()) {
+ out << ", ";
}
- out << " "
- << method->name()
- << "("
- << Method::GetJavaArgSignature(method->args());
+ out << method->name()
+ << "Callback cb";
+ }
- if (needsCallback) {
- if (!method->args().empty()) {
- out << ", ";
- }
+ out << ") {\n";
+ out.indent();
- out << method->name()
- << "Callback cb";
- }
+ out << "HwParcel request = new HwParcel();\n";
+ out << "request.writeInterfaceToken("
+ << superInterface->fullJavaName()
+ << ".kInterfaceName);\n";
- out << ") {\n";
- out.indent();
+ for (const auto &arg : method->args()) {
+ emitJavaReaderWriter(
+ out,
+ "request",
+ arg,
+ false /* isReader */);
+ }
- out << "HwParcel request = new HwParcel();\n";
- out << "request.writeInterfaceToken("
- << superInterface->fullJavaName()
- << ".kInterfaceName);\n";
+ out << "\nHwParcel reply = new HwParcel();\n"
+ << "mRemote.transact("
+ << method->getSerialId()
+ << " /* "
+ << method->name()
+ << " */, request, reply, ";
- for (const auto &arg : method->args()) {
+ if (method->isOneway()) {
+ out << "IHwBinder.FLAG_ONEWAY";
+ } else {
+ out << "0 /* flags */";
+ }
+
+ out << ");\n";
+
+ if (!method->isOneway()) {
+ out << "reply.verifySuccess();\n";
+ } else {
+ CHECK(!returnsValue);
+ }
+
+ out << "request.releaseTemporaryStorage();\n";
+
+ if (returnsValue) {
+ out << "\n";
+
+ for (const auto &arg : method->results()) {
emitJavaReaderWriter(
out,
- "request",
+ "reply",
arg,
- false /* isReader */);
+ true /* isReader */);
}
- out << "\nHwParcel reply = new HwParcel();\n"
- << "mRemote.transact("
- << method->getSerialId()
- << " /* "
- << method->name()
- << " */, request, reply, ";
+ if (needsCallback) {
+ out << "cb.onValues(";
- if (method->isOneway()) {
- out << "IHwBinder.FLAG_ONEWAY";
- } else {
- out << "0 /* flags */";
- }
-
- out << ");\n";
-
- if (!method->isOneway()) {
- out << "reply.verifySuccess();\n";
- } else {
- CHECK(!returnsValue);
- }
-
- out << "request.releaseTemporaryStorage();\n";
-
- if (returnsValue) {
- out << "\n";
-
+ bool firstField = true;
for (const auto &arg : method->results()) {
- emitJavaReaderWriter(
- out,
- "reply",
- arg,
- true /* isReader */);
- }
-
- if (needsCallback) {
- out << "cb.onValues(";
-
- bool firstField = true;
- for (const auto &arg : method->results()) {
- if (!firstField) {
- out << ", ";
- }
-
- out << arg->name();
- firstField = false;
+ if (!firstField) {
+ out << ", ";
}
- out << ");\n";
- } else {
- const std::string returnName = method->results()[0]->name();
- out << "return " << returnName << ";\n";
+ out << arg->name();
+ firstField = false;
}
- }
- out.unindent();
- out << "}\n\n";
+ out << ");\n";
+ } else {
+ const std::string returnName = method->results()[0]->name();
+ out << "return " << returnName << ";\n";
+ }
}
+
+ out.unindent();
+ out << "}\n\n";
}
out.unindent();
@@ -436,6 +431,21 @@
out.unindent();
out << "}\n\n";
+ // b/32383557 this is a hack. We need to change this if we have more reserved methods.
+ for (Method *method : iface->hidlReservedMethods()) {
+ std::string extra;
+ out << "public final "
+ << method->results()[0]->type().getJavaType(&extra)
+ << extra
+ << " "
+ << method->name()
+ << "() {\n";
+ out.indent();
+ method->javaImpl(out);
+ out.unindent();
+ out << "\n}\n\n";
+ }
+
out << "public IHwInterface queryLocalInterface(String descriptor) {\n";
out.indent();
// XXX what about potential superClasses?
@@ -470,111 +480,109 @@
out.indent();
- for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
- const Interface *superInterface = *it;
+ for (const auto &tuple : iface->allMethodsFromRoot()) {
+ const Method *method = tuple.method();
+ const Interface *superInterface = tuple.interface();
+ const bool returnsValue = !method->results().empty();
+ const bool needsCallback = method->results().size() > 1;
- for (const auto &method : superInterface->methods()) {
- const bool returnsValue = !method->results().empty();
- const bool needsCallback = method->results().size() > 1;
+ out << "case "
+ << method->getSerialId()
+ << " /* "
+ << method->name()
+ << " */:\n{\n";
- out << "case "
- << method->getSerialId()
- << " /* "
- << method->name()
- << " */:\n{\n";
+ out.indent();
+ out << "request.enforceInterface("
+ << superInterface->fullJavaName()
+ << ".kInterfaceName);\n\n";
+
+ for (const auto &arg : method->args()) {
+ emitJavaReaderWriter(
+ out,
+ "request",
+ arg,
+ true /* isReader */);
+ }
+
+ if (!needsCallback && returnsValue) {
+ const TypedVar *returnArg = method->results()[0];
+ std::string extra;
+
+ out << returnArg->type().getJavaType(&extra)
+ << extra
+ << " "
+ << returnArg->name()
+ << " = ";
+ }
+
+ out << method->name()
+ << "(";
+
+ bool firstField = true;
+ for (const auto &arg : method->args()) {
+ if (!firstField) {
+ out << ", ";
+ }
+
+ out << arg->name();
+
+ firstField = false;
+ }
+
+ if (needsCallback) {
+ if (!firstField) {
+ out << ", ";
+ }
+
+ out << "new " << method->name() << "Callback() {\n";
out.indent();
- out << "request.enforceInterface("
- << superInterface->fullJavaName()
- << ".kInterfaceName);\n\n";
+ out << "@Override\n"
+ << "public void onValues("
+ << Method::GetJavaArgSignature(method->results())
+ << ") {\n";
- for (const auto &arg : method->args()) {
+ out.indent();
+ out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+
+ for (const auto &arg : method->results()) {
emitJavaReaderWriter(
out,
- "request",
+ "reply",
arg,
- true /* isReader */);
+ false /* isReader */);
}
- if (!needsCallback && returnsValue) {
- const TypedVar *returnArg = method->results()[0];
- std::string extra;
+ out << "reply.send();\n"
+ << "}}";
- out << returnArg->type().getJavaType(&extra)
- << extra
- << " "
- << returnArg->name()
- << " = ";
- }
-
- out << method->name()
- << "(";
-
- bool firstField = true;
- for (const auto &arg : method->args()) {
- if (!firstField) {
- out << ", ";
- }
-
- out << arg->name();
-
- firstField = false;
- }
-
- if (needsCallback) {
- if (!firstField) {
- out << ", ";
- }
-
- out << "new " << method->name() << "Callback() {\n";
- out.indent();
-
- out << "@Override\n"
- << "public void onValues("
- << Method::GetJavaArgSignature(method->results())
- << ") {\n";
-
- out.indent();
- out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
-
- for (const auto &arg : method->results()) {
- emitJavaReaderWriter(
- out,
- "reply",
- arg,
- false /* isReader */);
- }
-
- out << "reply.send();\n"
- << "}}";
-
- out.unindent();
- out.unindent();
- }
-
- out << ");\n";
-
- if (!needsCallback) {
- out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
-
- if (returnsValue) {
- const TypedVar *returnArg = method->results()[0];
-
- emitJavaReaderWriter(
- out,
- "reply",
- returnArg,
- false /* isReader */);
- }
-
- out << "reply.send();\n";
- }
-
- out << "break;\n";
out.unindent();
- out << "}\n\n";
+ out.unindent();
}
+
+ out << ");\n";
+
+ if (!needsCallback) {
+ out << "reply.writeStatus(HwParcel.STATUS_SUCCESS);\n";
+
+ if (returnsValue) {
+ const TypedVar *returnArg = method->results()[0];
+
+ emitJavaReaderWriter(
+ out,
+ "reply",
+ returnArg,
+ false /* isReader */);
+ }
+
+ out << "reply.send();\n";
+ }
+
+ out << "break;\n";
+ out.unindent();
+ out << "}\n\n";
}
out.unindent();
diff --git a/generateVts.cpp b/generateVts.cpp
index 2eba598..35eb0d0 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -121,11 +121,7 @@
out << "interface: {\n";
out.indent();
- std::vector<const Interface *> chain;
- while (iface != NULL) {
- chain.push_back(iface);
- iface = iface->superType();
- }
+ std::vector<const Interface *> chain = iface->typeChain();
// Generate all the attribute declarations first.
for (auto it = chain.rbegin(); it != chain.rend(); ++it) {