Merge "Special consideration for passing vec<interface> or vec<IFoo> to and from"
diff --git a/CompoundType.cpp b/CompoundType.cpp
index f8ddc06..63514d8 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -35,7 +35,10 @@
for (const auto &field : *fields) {
const Type &type = field->type();
- if (type.isBinder()) {
+ if (type.isBinder()
+ || (type.isVector()
+ && static_cast<const VectorType *>(
+ &type)->isVectorOfBinders())) {
*errorMsg =
"Structs/Unions must not contain references to interfaces.";
diff --git a/VectorType.cpp b/VectorType.cpp
index d7eb581..461a05b 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -30,11 +30,20 @@
mElementType->addNamedTypesToSet(set);
}
+bool VectorType::isVector() const {
+ return true;
+}
+
+bool VectorType::isVectorOfBinders() const {
+ return mElementType->isBinder();
+}
+
std::string VectorType::getCppType(StorageMode mode,
std::string *extra,
bool specifyNamespaces) const {
std::string elementExtra;
- const std::string elementBase = mElementType->getCppType(&elementExtra, specifyNamespaces);
+ const std::string elementBase =
+ mElementType->getCppType(&elementExtra, specifyNamespaces);
const std::string base =
std::string(specifyNamespaces ? "::android::hardware::" : "")
@@ -53,7 +62,13 @@
return "const " + base + "&";
case StorageMode_Result:
+ {
+ if (isVectorOfBinders()) {
+ return base;
+ }
+
return "const " + base + "*";
+ }
}
}
@@ -84,6 +99,13 @@
bool parcelObjIsPointer,
bool isReader,
ErrorMode mode) const {
+ if (isVectorOfBinders()) {
+ emitReaderWriterForVectorOfBinders(
+ out, name, parcelObj, parcelObjIsPointer, isReader, mode);
+
+ return;
+ }
+
std::string baseExtra;
std::string baseType = mElementType->getCppType(&baseExtra);
@@ -142,6 +164,92 @@
"0 /* parentOffset */");
}
+void VectorType::emitReaderWriterForVectorOfBinders(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << "{\n";
+ out.indent();
+
+ const std::string sizeName = "_hidl_" + name + "_size";
+
+ out << "uint64_t "
+ << sizeName
+ << ";\n";
+
+ out << "_hidl_err = "
+ << parcelObjDeref
+ << "readUint64(&"
+ << sizeName
+ << ");\n";
+
+ handleError(out, mode);
+
+ out << name
+ << ".resize("
+ << sizeName
+ << ");\n\n"
+ << "for (size_t _hidl_index = 0; _hidl_index < "
+ << sizeName
+ << "; ++_hidl_index) {\n";
+
+ out.indent();
+
+ std::string extra;
+ out << mElementType->getCppType(&extra, true /* specifyNamespaces */)
+ << " _hidl_binder;\n";
+
+ mElementType->emitReaderWriter(
+ out,
+ "_hidl_binder",
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode);
+
+ out << name
+ << "[_hidl_index] = _hidl_binder;\n";
+
+ out.unindent();
+ out << "}\n";
+
+ out.unindent();
+ out << "}\n";
+ } else {
+ out << "_hidl_err = "
+ << parcelObjDeref
+ << "writeUint64("
+ << name
+ << ".size());\n";
+
+ handleError(out, mode);
+
+ out << "for (size_t _hidl_index = 0; _hidl_index < "
+ << name
+ << ".size(); ++_hidl_index) {\n";
+
+ out.indent();
+
+ mElementType->emitReaderWriter(
+ out,
+ name + "[_hidl_index]",
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode);
+
+ out.unindent();
+ out << "}\n";
+ }
+}
+
void VectorType::emitReaderWriterEmbedded(
Formatter &out,
size_t depth,
@@ -580,7 +688,7 @@
}
bool VectorType::resultNeedsDeref() const {
- return true;
+ return !isVectorOfBinders();
}
status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
@@ -621,6 +729,10 @@
return false;
}
+ if (isVectorOfBinders()) {
+ return false;
+ }
+
return true;
}
diff --git a/VectorType.h b/VectorType.h
index e093777..333d69d 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -25,6 +25,9 @@
struct VectorType : public TemplatedType {
VectorType();
+ bool isVector() const override;
+ bool isVectorOfBinders() const;
+
void addNamedTypesToSet(std::set<const FQName> &set) const override;
std::string getCppType(
@@ -144,6 +147,14 @@
const std::string &childName,
const std::string &childOffsetText) const;
+ void emitReaderWriterForVectorOfBinders(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const;
+
DISALLOW_COPY_AND_ASSIGN(VectorType);
};
diff --git a/generateJava.cpp b/generateJava.cpp
index 2b14cf0..6ae84fe 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -108,8 +108,8 @@
"ERROR: This interface is not Java compatible. The Java backend"
" does NOT support union types nor native handles. "
"In addition, vectors of arrays are limited to at most "
- "one-dimensional arrays and vectors of vectors are not "
- "supported.\n");
+ "one-dimensional arrays and vectors of {vectors,interfaces} are"
+ " not supported.\n");
return UNKNOWN_ERROR;
}
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 1b6ae5c..b79f195 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -673,7 +673,7 @@
}
| TEMPLATED '<' type '>'
{
- if ($3->isBinder()) {
+ if (!$1->isVector() && $3->isBinder()) {
std::cerr << "ERROR: TemplatedType of interface types are not "
<< "supported. at " << @3 << "\n";
diff --git a/test/main.cpp b/test/main.cpp
index 97ac84f..6063bef 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -59,11 +59,12 @@
static std::string gServiceName;
// end static storage
+using ::android::hardware::tests::foo::V1_0::Abc;
using ::android::hardware::tests::foo::V1_0::IFoo;
using ::android::hardware::tests::foo::V1_0::IFooCallback;
+using ::android::hardware::tests::foo::V1_0::ISimple;
using ::android::hardware::tests::bar::V1_0::IBar;
using ::android::hardware::tests::bar::V1_0::IHwBar;
-using ::android::hardware::tests::foo::V1_0::Abc;
using ::android::hardware::tests::pointer::V1_0::IGraph;
using ::android::hardware::tests::pointer::V1_0::IPointer;
using ::android::hardware::IPCThreadState;
@@ -129,6 +130,19 @@
// NOTE: duplicated code in Foo.cpp
using std::to_string;
+struct Simple : public ISimple {
+ Simple(int32_t cookie)
+ : mCookie(cookie) {
+ }
+
+ Return<int32_t> getCookie() override {
+ return mCookie;
+ }
+
+private:
+ int32_t mCookie;
+};
+
static std::string to_string(const IFoo::StringMatrix5x3 &M);
static std::string to_string(const IFoo::StringMatrix3x5 &M);
static std::string to_string(const hidl_string &s);
@@ -768,6 +782,51 @@
}));
}
+TEST_F(HidlTest, FooHaveAVectorOfInterfacesTest) {
+ hidl_vec<sp<ISimple> > in;
+ in.resize(16);
+ for (size_t i = 0; i < in.size(); ++i) {
+ in[i] = new Simple(i);
+ }
+
+ EXPECT_OK(foo->haveAVectorOfInterfaces(
+ in,
+ [&](const auto &out) {
+ EXPECT_EQ(in.size(), out.size());
+ for (size_t i = 0; i < in.size(); ++i) {
+ int32_t inCookie = in[i]->getCookie();
+ int32_t outCookie = out[i]->getCookie();
+ EXPECT_EQ(inCookie, outCookie);
+ }
+ }));
+}
+
+TEST_F(HidlTest, FooHaveAVectorOfGenericInterfacesTest) {
+ using ::android::hardware::tests::foo::V1_0::IHwSimple;
+ using ::android::hardware::tests::foo::V1_0::BnSimple;
+
+ hidl_vec<sp<android::hardware::IBinder> > in;
+ in.resize(16);
+ for (size_t i = 0; i < in.size(); ++i) {
+ sp<BnSimple> simpleStub = new BnSimple(new Simple(i));
+ in[i] = IHwSimple::asBinder(simpleStub);
+ }
+
+ EXPECT_OK(foo->haveAVectorOfGenericInterfaces(
+ in,
+ [&](const auto &out) {
+ EXPECT_EQ(in.size(), out.size());
+ for (size_t i = 0; i < in.size(); ++i) {
+ sp<ISimple> inSimple = IHwSimple::asInterface(in[i]);
+ sp<ISimple> outSimple = IHwSimple::asInterface(out[i]);
+
+ int32_t inCookie = inSimple->getCookie();
+ int32_t outCookie = outSimple->getCookie();
+ EXPECT_EQ(inCookie, outCookie);
+ }
+ }));
+}
+
TEST_F(HidlTest, BarThisIsNewTest) {
// Now the tricky part, get access to the derived interface.
ALOGI("CLIENT call thisIsNew.");