Merge "GTest test-cases for HIDL safe unions in Java"
diff --git a/AST.cpp b/AST.cpp
index 81f8c0b..de69965 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -83,8 +83,8 @@
return mRootScope.getInterface() != nullptr;
}
-bool AST::containsInterfaces() const {
- return mRootScope.containsInterfaces();
+bool AST::definesInterfaces() const {
+ return mRootScope.definesInterfaces();
}
status_t AST::postParse() {
diff --git a/AST.h b/AST.h
index 4de98bd..3e8e5a5 100644
--- a/AST.h
+++ b/AST.h
@@ -53,7 +53,7 @@
// package and version really.
FQName package() const;
bool isInterface() const;
- bool containsInterfaces() const;
+ bool definesInterfaces() const;
// Adds package, version and scope stack to local name
FQName makeFullName(const char* localName, Scope* scope) const;
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 5155a27..2d672df 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -156,10 +156,6 @@
return base;
}
-std::string ArrayType::getJavaWrapperType() const {
- return mElementType->getJavaWrapperType();
-}
-
std::string ArrayType::getVtsType() const {
return "TYPE_ARRAY";
}
@@ -366,7 +362,8 @@
out << streamName << ".append(java.util.Arrays."
<< (countDimensions() > 1 ? "deepToString" : "toString")
<< "("
- << name << "));\n";
+ << name
+ << "));\n";
}
@@ -434,15 +431,17 @@
void ArrayType::emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const {
- std::string typeName = getJavaType(false /* forInitializer */);
- std::string initName = getJavaType(true /* forInitializer */);
+ const std::string typeName = getJavaType(false /* forInitializer */);
+ const std::string fieldDeclaration = "final " + typeName + " " + fieldName;
- out << "final "
- << typeName
- << " "
- << fieldName
+ emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
+}
+
+void ArrayType::emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const {
+ out << declaredFieldName
<< " = new "
- << initName
+ << getJavaType(true /* forInitializer */)
<< ";\n";
}
@@ -488,15 +487,13 @@
indexString += "[" + iteratorName + "]";
}
- if (isReader && mElementType->isCompoundType()) {
- std::string typeName =
- mElementType->getJavaType(false /* forInitializer */);
+ const bool isIndexed = (loopDimensions > 0);
+ const std::string fieldNameWithCast = isIndexed
+ ? "(" + getJavaTypeCast(fieldName) + ")" + indexString
+ : getJavaTypeCast(fieldName);
- out << fieldName
- << indexString
- << " = new "
- << typeName
- << "();\n";
+ if (isReader && mElementType->isCompoundType()) {
+ mElementType->emitJavaFieldDefaultInitialValue(out, fieldNameWithCast);
}
if (!isPrimitiveArray) {
@@ -505,7 +502,7 @@
depth + 1,
parcelName,
blobName,
- fieldName + indexString,
+ fieldNameWithCast,
offsetName,
isReader);
@@ -521,8 +518,7 @@
<< "Array("
<< offsetName
<< ", "
- << fieldName
- << indexString
+ << fieldNameWithCast
<< ", "
<< mSizes.back()->javaValue()
<< " /* size */);\n";
@@ -533,8 +529,7 @@
<< "Array("
<< offsetName
<< ", "
- << fieldName
- << indexString
+ << fieldNameWithCast
<< ");\n";
}
diff --git a/ArrayType.h b/ArrayType.h
index 2c13a33..2ced071 100644
--- a/ArrayType.h
+++ b/ArrayType.h
@@ -56,8 +56,6 @@
std::string getJavaType(bool forInitializer) const override;
- std::string getJavaWrapperType() const override;
-
std::string getVtsType() const override;
void emitReaderWriter(
@@ -121,6 +119,9 @@
void emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const override;
+ void emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const override;
+
void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
diff --git a/CompoundType.cpp b/CompoundType.cpp
index db7c75a..178b132 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -50,12 +50,18 @@
const Type& type = field->type();
if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
- std::cerr << "ERROR: Struct/Union must not contain references to interfaces at "
+ std::cerr << "ERROR: Struct/union cannot contain vectors of interfaces at "
<< field->location() << "\n";
return UNKNOWN_ERROR;
}
if (mStyle == STYLE_UNION) {
+ if (type.isBinder()) {
+ std::cerr << "ERROR: Union cannot contain interfaces at " << field->location()
+ << "\n";
+ return UNKNOWN_ERROR;
+ }
+
if (type.needsEmbeddedReadWrite()) {
std::cerr << "ERROR: Union must not contain any types that need fixup at "
<< field->location() << "\n";
@@ -392,10 +398,13 @@
void CompoundType::emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const {
- out << "final "
- << fullJavaName()
- << " "
- << fieldName
+ const std::string fieldDeclaration = "final " + fullJavaName() + " " + fieldName;
+ emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
+}
+
+void CompoundType::emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const {
+ out << declaredFieldName
<< " = new "
<< fullJavaName()
<< "();\n";
@@ -410,8 +419,9 @@
const std::string &offset,
bool isReader) const {
if (isReader) {
- out << fieldName
- << ".readEmbeddedFromParcel("
+ out << "("
+ << getJavaTypeCast(fieldName)
+ << ").readEmbeddedFromParcel("
<< parcelName
<< ", "
<< blobName
@@ -977,7 +987,7 @@
<< "& other) ";
out.block([&] {
- out << "switch(other.hidl_d) ";
+ out << "switch (other.hidl_d) ";
out.block([&] {
for (const auto& field : *mFields) {
@@ -1015,7 +1025,7 @@
<< "::hidl_destructUnion() ";
out.block([&] {
- out << "switch(hidl_d) ";
+ out << "switch (hidl_d) ";
out.block([&] {
for (const auto& field : *mFields) {
@@ -1181,7 +1191,6 @@
}
}
-// TODO(b/79878527): Implement Java bindings for safe unions
void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
out << "public final ";
@@ -1197,15 +1206,128 @@
Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
- for (const auto& field : *mFields) {
- field->emitDocComment(out);
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ const std::string discriminatorStorageType = (
+ getUnionDiscriminatorType()->getJavaType(false));
- out << "public ";
+ out << "public static final class hidl_discriminator ";
+ out.block([&] {
+ std::vector<std::string> enumNames;
+ for (const auto& field : *mFields) {
+ enumNames.push_back(field->name());
+ }
+ enumNames.push_back("hidl_no_init");
- field->type().emitJavaFieldInitializer(out, field->name());
- }
+ for (size_t idx = 0; idx < enumNames.size(); idx++) {
+ out << "public static final "
+ << discriminatorStorageType
+ << " "
+ << enumNames[idx]
+ << " = "
+ << idx
+ << ";\n";
+ }
- if (!mFields->empty()) {
+ out << "\n"
+ << "public static final String getName("
+ << discriminatorStorageType
+ << " value) ";
+
+ out.block([&] {
+ out << "switch (value) ";
+ out.block([&] {
+ for (size_t idx = 0; idx < enumNames.size(); idx++) {
+ out << "case "
+ << idx
+ << ": { return \""
+ << enumNames[idx]
+ << "\"; }\n";
+ }
+ out << "default: { return \"Unknown\"; }\n";
+ }).endl();
+ }).endl().endl();
+
+ out << "private hidl_discriminator() {}\n";
+ }).endl().endl();
+
+ out << "private "
+ << discriminatorStorageType
+ << " hidl_d = hidl_discriminator.hidl_no_init;\n";
+
+ out << "private Object hidl_o;\n\n";
+
+ for (const auto& field : *mFields) {
+ // Setter
+ out << "public void "
+ << field->name()
+ << "("
+ << field->type().getJavaType(false)
+ << " "
+ << field->name()
+ << ") ";
+
+ out.block([&] {
+ out << "hidl_d = hidl_discriminator."
+ << field->name()
+ << ";\n";
+
+ out << "hidl_o = "
+ << field->name()
+ << ";\n";
+ }).endl().endl();
+
+ // Getter
+ out << "public "
+ << field->type().getJavaType(false)
+ << " "
+ << field->name()
+ << "() ";
+
+ out.block([&] {
+ out << "if (hidl_d != hidl_discriminator."
+ << field->name()
+ << ") ";
+
+ out.block([&] {
+ out << "String className = (hidl_o != null) ? "
+ << "hidl_o.getClass().getName() : \"null\";\n";
+
+ out << "throw new IllegalStateException(\n";
+ out.indent(2, [&] {
+ out << "\"Read access to inactive union components is disallowed. \" +\n"
+ << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n"
+ << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n"
+ << "\"hidl_o is of type \" + className + \".\");\n";
+ });
+ }).endl();
+
+ out << "if (hidl_o != null && !"
+ << field->type().getJavaTypeClass()
+ << ".class.isInstance(hidl_o)) ";
+
+ out.block([&] {
+ out << "throw new Error(\"Union is in a corrupted state.\");\n";
+ }).endl();
+
+ out << "return ("
+ << field->type().getJavaTypeCast("hidl_o")
+ << ");\n";
+ }).endl().endl();
+ }
+
+ out << "// Utility method\n"
+ << "public "
+ << discriminatorStorageType
+ << " getDiscriminator() { return hidl_d; }\n\n";
+
+ } else if (!mFields->empty()) {
+ for (const auto& field : *mFields) {
+ field->emitDocComment(out);
+
+ out << "public ";
+ field->type().emitJavaFieldInitializer(out, field->name());
+ }
+
out << "\n";
}
@@ -1225,14 +1347,27 @@
out << "return false;\n";
}).endl();
out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
- for (const auto &field : *mFields) {
- std::string condition = (field->type().isScalar() || field->type().isEnum())
- ? "this." + field->name() + " != other." + field->name()
- : ("!android.os.HidlSupport.deepEquals(this." + field->name()
- + ", other." + field->name() + ")");
- out.sIf(condition, [&] {
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out.sIf("this.hidl_d != other.hidl_d", [&] {
out << "return false;\n";
}).endl();
+ out.sIf("this.hidl_d == hidl_discriminator.hidl_no_init", [&] {
+ out << "return false;\n";
+ }).endl();
+ out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
+ out << "return false;\n";
+ }).endl();
+ } else if (!mFields->empty()) {
+ for (const auto &field : *mFields) {
+ std::string condition = (field->type().isScalar() || field->type().isEnum())
+ ? "this." + field->name() + " != other." + field->name()
+ : ("!android.os.HidlSupport.deepEquals(this." + field->name()
+ + ", other." + field->name() + ")");
+ out.sIf(condition, [&] {
+ out << "return false;\n";
+ }).endl();
+ }
}
out << "return true;\n";
}).endl().endl();
@@ -1241,9 +1376,14 @@
out.block([&] {
out << "return java.util.Objects.hash(\n";
out.indent(2, [&] {
- out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
- out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
- });
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
+ << "java.util.Objects.hashCode(this.hidl_d)";
+ } else {
+ out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
+ out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
+ });
+ }
});
out << ");\n";
}).endl().endl();
@@ -1257,32 +1397,94 @@
out.block([&] {
out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
<< "builder.append(\"{\");\n";
- for (const auto &field : *mFields) {
- out << "builder.append(\"";
- if (field != *(mFields->begin())) {
- out << ", ";
- }
- out << "." << field->name() << " = \");\n";
- field->type().emitJavaDump(out, "builder", "this." + field->name());
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "switch (this.hidl_d) {\n";
+ out.indent();
}
+
+ for (const auto &field : *mFields) {
+ if (mStyle == STYLE_SAFE_UNION) {
+ out << "case hidl_discriminator."
+ << field->name()
+ << ": ";
+
+ out.block([&] {
+ out << "builder.append(\""
+ << "."
+ << field->name()
+ << " = \");\n";
+
+ field->type().emitJavaDump(out, "builder", "this." + field->name() + "()");
+ out << "break;\n";
+ }).endl();
+ }
+ else {
+ out << "builder.append(\"";
+ if (field != *(mFields->begin())) {
+ out << ", ";
+ }
+ out << "." << field->name() << " = \");\n";
+ field->type().emitJavaDump(out, "builder", "this." + field->name());
+ }
+ }
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "case hidl_discriminator.hidl_no_init: { break; }\n"
+ << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
+
+ out.unindent();
+ out << "}\n";
+ }
+
out << "builder.append(\"}\");\nreturn builder.toString();\n";
}).endl().endl();
- size_t structAlign, structSize;
- getAlignmentAndSize(&structAlign, &structSize);
+ CompoundLayout layout = getCompoundAlignmentAndSize();
////////////////////////////////////////////////////////////////////////////
out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
out.indent();
if (containsInterface()) {
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "hidl_d = ";
+ getUnionDiscriminatorType()->emitJavaReaderWriter(
+ out, "parcel", "hidl_d", true);
+
+ out << "switch (hidl_d) {\n";
+ out.indent();
+ }
+
for (const auto& field : *mFields) {
- out << field->name() << " = ";
- field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
+ if (mStyle == STYLE_SAFE_UNION) {
+ out << "case hidl_discriminator."
+ << field->name()
+ << ": ";
+
+ out.block([&] {
+ out << "hidl_o = ";
+ field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true);
+
+ out << "break;\n";
+ }).endl();
+ } else {
+ out << field->name() << " = ";
+ field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
+ }
+ }
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "case hidl_discriminator.hidl_no_init: { break; }\n"
+ << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
+
+ out.unindent();
+ out << "}\n";
}
} else {
out << "android.os.HwBlob blob = parcel.readBuffer(";
- out << structSize << "/* size */);\n";
+ out << layout.overall.size << " /* size */);\n";
out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
}
out.unindent();
@@ -1327,17 +1529,51 @@
out.indent(2);
out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
- size_t offset = 0;
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
+ "_hidl_offset + " + std::to_string(layout.discriminator.offset),
+ true /* isReader */);
+
+ out << "switch (this.hidl_d) {\n";
+ out.indent();
+ }
+
+ size_t offset = layout.innerStruct.offset;
for (const auto& field : *mFields) {
- size_t fieldAlign, fieldSize;
- field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
- offset += Layout::getPad(offset, fieldAlign);
+ if (mStyle == STYLE_SAFE_UNION) {
+ out << "case hidl_discriminator."
+ << field->name()
+ << ": ";
- field->type().emitJavaFieldReaderWriter(
- out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
- "_hidl_offset + " + std::to_string(offset), true /* isReader */);
- offset += fieldSize;
+ out.block([&] {
+ field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
+ field->type().emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o",
+ "_hidl_offset + " + std::to_string(offset), true /* isReader */);
+
+ out << "break;\n";
+ }).endl();
+ } else {
+ size_t fieldAlign, fieldSize;
+ field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
+
+ offset += Layout::getPad(offset, fieldAlign);
+ field->type().emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
+ "_hidl_offset + " + std::to_string(offset), true /* isReader */);
+ offset += fieldSize;
+ }
+ }
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "case hidl_discriminator.hidl_no_init: { break; }\n"
+ << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
+
+ out.unindent();
+ out << "}\n";
}
out.unindent();
out << "}\n\n";
@@ -1349,11 +1585,39 @@
out.indent();
if (containsInterface()) {
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ getUnionDiscriminatorType()->emitJavaReaderWriter(
+ out, "parcel", "hidl_d", false);
+
+ out << "switch (this.hidl_d) {\n";
+ out.indent();
+ }
+
for (const auto& field : *mFields) {
- field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
+ if (mStyle == STYLE_SAFE_UNION) {
+ out << "case hidl_discriminator."
+ << field->name()
+ << ": ";
+
+ out.block([&] {
+ field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false);
+ out << "break;\n";
+ }).endl();
+ } else {
+ field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
+ }
+ }
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "case hidl_discriminator.hidl_no_init: { break; }\n"
+ << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
+
+ out.unindent();
+ out << "}\n";
}
} else {
- out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << structSize
+ out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
+ << layout.overall.size
<< " /* size */);\n";
out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
@@ -1371,10 +1635,10 @@
if (containsInterface()) {
out << "parcel.writeInt32(_hidl_vec.size());\n";
- out << "for(" << fullJavaName() << " tmp: _hidl_vec)\n";
- out.indent();
- emitJavaReaderWriter(out, "parcel", "tmp", false);
- out.unindent();
+ out << "for(" << fullJavaName() << " tmp: _hidl_vec) ";
+ out.block([&] {
+ emitJavaReaderWriter(out, "parcel", "tmp", false);
+ }).endl();
} else {
out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
<< " /* sizeof(hidl_vec<T>) */);\n";
@@ -1390,25 +1654,56 @@
////////////////////////////////////////////////////////////////////////////
if (containsInterface()) {
- out << "// writeEmbeddedFromParcel() is not generated\n";
+ out << "// writeEmbeddedToBlob() is not generated\n";
} else {
out << "public final void writeEmbeddedToBlob(\n";
out.indent(2);
out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
- size_t offset = 0;
- for (const auto& field : *mFields) {
- size_t fieldAlign, fieldSize;
- field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
- offset += Layout::getPad(offset, fieldAlign);
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
+ "_hidl_offset + " + std::to_string(layout.discriminator.offset),
+ false /* isReader */);
- field->type().emitJavaFieldReaderWriter(
- out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
- "_hidl_offset + " + std::to_string(offset), false /* isReader */);
- offset += fieldSize;
+ out << "switch (this.hidl_d) {\n";
+ out.indent();
}
+ size_t offset = layout.innerStruct.offset;
+ for (const auto& field : *mFields) {
+ if (mStyle == STYLE_SAFE_UNION) {
+ out << "case hidl_discriminator."
+ << field->name()
+ << ": ";
+
+ out.block([&] {
+ field->type().emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()",
+ "_hidl_offset + " + std::to_string(offset), false /* isReader */);
+
+ out << "break;\n";
+ }).endl();
+ } else {
+ size_t fieldAlign, fieldSize;
+ field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
+
+ offset += Layout::getPad(offset, fieldAlign);
+ field->type().emitJavaFieldReaderWriter(
+ out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
+ "_hidl_offset + " + std::to_string(offset), false /* isReader */);
+ offset += fieldSize;
+ }
+ }
+
+ if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ out << "case hidl_discriminator.hidl_no_init: { break; }\n"
+ << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
+
+ out.unindent();
+ out << "}\n";
+ }
out.unindent();
out << "}\n";
}
@@ -1723,7 +2018,7 @@
}
bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
- if (mStyle != STYLE_STRUCT) { // TODO(natre): Update
+ if (mStyle == STYLE_UNION) {
return false;
}
diff --git a/CompoundType.h b/CompoundType.h
index 305162b..e2b6612 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -110,6 +110,9 @@
void emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const override;
+ void emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const override;
+
void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
diff --git a/Coordinator.cpp b/Coordinator.cpp
index 9a2009c..0e77ef3 100644
--- a/Coordinator.cpp
+++ b/Coordinator.cpp
@@ -320,7 +320,7 @@
fqName.name().c_str());
err = UNKNOWN_ERROR;
- } else if ((*ast)->containsInterfaces()) {
+ } else if ((*ast)->definesInterfaces()) {
fprintf(stderr,
"ERROR: types.hal file at '%s' declares at least one "
"interface type.\n",
diff --git a/EnumType.cpp b/EnumType.cpp
index d7fca9c..2c9c0cc 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -168,8 +168,8 @@
return mStorageType->resolveToScalarType()->getJavaSuffix();
}
-std::string EnumType::getJavaWrapperType() const {
- return mStorageType->resolveToScalarType()->getJavaWrapperType();
+std::string EnumType::getJavaTypeClass() const {
+ return mStorageType->resolveToScalarType()->getJavaTypeClass();
}
std::string EnumType::getVtsType() const {
@@ -185,8 +185,8 @@
return resolveToScalarType()->getJavaType(forInitializer);
}
-std::string EnumType::getBitfieldJavaWrapperType() const {
- return resolveToScalarType()->getJavaWrapperType();
+std::string EnumType::getBitfieldJavaTypeClass() const {
+ return resolveToScalarType()->getJavaTypeClass();
}
LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
@@ -590,7 +590,6 @@
}).endl();
auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
- auto bitfieldWrapperType = getBitfieldJavaWrapperType();
out << "\n"
<< "public static final String dumpBitfield("
<< bitfieldType << " o) ";
@@ -944,8 +943,8 @@
return resolveToScalarType()->getJavaSuffix();
}
-std::string BitFieldType::getJavaWrapperType() const {
- return getElementEnumType()->getBitfieldJavaWrapperType();
+std::string BitFieldType::getJavaTypeClass() const {
+ return getElementEnumType()->getBitfieldJavaTypeClass();
}
std::string BitFieldType::getVtsType() const {
diff --git a/EnumType.h b/EnumType.h
index 37fa00e..309eeb0 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -52,16 +52,15 @@
bool specifyNamespaces) const override;
std::string getJavaType(bool forInitializer) const override;
+ std::string getJavaTypeClass() const override;
std::string getJavaSuffix() const override;
- std::string getJavaWrapperType() const override;
-
std::string getVtsType() const override;
std::string getBitfieldCppType(StorageMode mode, bool specifyNamespaces = true) const;
std::string getBitfieldJavaType(bool forInitializer = false) const;
- std::string getBitfieldJavaWrapperType() const;
+ std::string getBitfieldJavaTypeClass() const;
// Return the type that corresponds to bitfield<T>.
const BitFieldType* getBitfieldType() const;
@@ -184,11 +183,10 @@
bool specifyNamespaces) const override;
std::string getJavaType(bool forInitializer) const override;
+ std::string getJavaTypeClass() const override;
std::string getJavaSuffix() const override;
- std::string getJavaWrapperType() const override;
-
std::string getVtsType() const override;
const EnumType* getEnumType() const;
diff --git a/ScalarType.cpp b/ScalarType.cpp
index 2e2e7b2..dc02b69 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -83,7 +83,7 @@
return kName[mKind];
}
-std::string ScalarType::getJavaWrapperType() const {
+std::string ScalarType::getJavaTypeClass() const {
static const char *const kName[] = {
"Boolean",
"Byte",
@@ -225,7 +225,7 @@
case KIND_INT16: // fallthrough
case KIND_UINT16: {
// Because Byte and Short doesn't have toHexString, we have to use Integer.toHexString.
- out << "Integer.toHexString(" << getJavaWrapperType() << ".toUnsignedInt(("
+ out << "Integer.toHexString(" << getJavaTypeClass() << ".toUnsignedInt(("
<< getJavaType(false /* forInitializer */) << ")(" << name << ")))";
break;
}
@@ -233,7 +233,7 @@
case KIND_UINT32: // fallthrough
case KIND_INT64: // fallthrough
case KIND_UINT64: {
- out << getJavaWrapperType() << ".toHexString(" << name << ")";
+ out << getJavaTypeClass() << ".toHexString(" << name << ")";
break;
}
case KIND_FLOAT: // fallthrough
diff --git a/ScalarType.h b/ScalarType.h
index 86305b8..10fb540 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -54,8 +54,8 @@
bool specifyNamespaces) const override;
std::string getJavaType(bool forInitializer) const override;
+ std::string getJavaTypeClass() const override;
- std::string getJavaWrapperType() const override;
std::string getJavaSuffix() const override;
std::string getVtsType() const override;
diff --git a/Scope.cpp b/Scope.cpp
index bff097f..fcf67bf 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -96,7 +96,7 @@
return NULL;
}
-bool Scope::containsInterfaces() const {
+bool Scope::definesInterfaces() const {
for (const NamedType *type : mTypes) {
if (type->isInterface()) {
return true;
diff --git a/Scope.h b/Scope.h
index e8c9431..cfef50e 100644
--- a/Scope.h
+++ b/Scope.h
@@ -51,7 +51,7 @@
// Returns the single interface or NULL.
Interface *getInterface() const;
- bool containsInterfaces() const;
+ bool definesInterfaces() const;
const std::vector<Annotation*>& annotations() const;
diff --git a/StringType.cpp b/StringType.cpp
index a07086f..b4f72be 100644
--- a/StringType.cpp
+++ b/StringType.cpp
@@ -150,9 +150,12 @@
void StringType::emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const {
- out << "String "
- << fieldName
- << " = new String();\n";
+ emitJavaFieldDefaultInitialValue(out, "String " + fieldName);
+}
+
+void StringType::emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const {
+ out << declaredFieldName << " = new String();\n";
}
void StringType::emitJavaFieldReaderWriter(
@@ -180,7 +183,7 @@
// hidl_string's embedded buffer is never null(able), because it defaults to a
// buffer containing an empty string.
- out << fieldName << ".getBytes().length + 1,\n"
+ out << "(" << getJavaTypeCast(fieldName) << ").getBytes().length + 1,\n"
<< blobName
<< ".handle(),\n"
<< offset
diff --git a/StringType.h b/StringType.h
index a4e3691..2050875 100644
--- a/StringType.h
+++ b/StringType.h
@@ -65,6 +65,9 @@
void emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const override;
+ void emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const override;
+
void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
diff --git a/Type.cpp b/Type.cpp
index 00bbae3..33a8aa1 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -385,10 +385,14 @@
return std::string();
}
-std::string Type::getJavaWrapperType() const {
+std::string Type::getJavaTypeClass() const {
return getJavaType();
}
+std::string Type::getJavaTypeCast(const std::string& objName) const {
+ return "(" + getJavaType() + ") " + objName;
+}
+
std::string Type::getJavaSuffix() const {
CHECK(!"Should not be here");
return std::string();
@@ -513,6 +517,8 @@
<< ";\n";
}
+void Type::emitJavaFieldDefaultInitialValue(Formatter &, const std::string &) const {}
+
void Type::emitJavaFieldReaderWriter(
Formatter &,
size_t,
diff --git a/Type.h b/Type.h
index 1653cdd..6426de4 100644
--- a/Type.h
+++ b/Type.h
@@ -170,7 +170,13 @@
// otherwise (and by default), they are omitted, i.e. [][].
virtual std::string getJavaType(bool forInitializer = false) const;
- virtual std::string getJavaWrapperType() const;
+ // Identical to getJavaType() for most types, except: primitives, in which
+ // case the wrapper type is returned, and generics (such as ArrayList<?>),
+ // where the type specialization is omitted to facilitate use of
+ // instanceof or class.isInstance().
+ virtual std::string getJavaTypeClass() const;
+
+ virtual std::string getJavaTypeCast(const std::string& objName) const;
virtual std::string getJavaSuffix() const;
virtual std::string getVtsType() const;
@@ -249,6 +255,10 @@
Formatter &out,
const std::string &fieldName) const;
+ virtual void emitJavaFieldDefaultInitialValue(
+ Formatter &out,
+ const std::string &declaredFieldName) const;
+
virtual void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
diff --git a/VectorType.cpp b/VectorType.cpp
index 03604dc..3ba3df5 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -45,6 +45,9 @@
return true;
}
if (elementType->isCompoundType()) {
+ if (static_cast<const CompoundType*>(elementType)->containsInterface()) {
+ return false;
+ }
return true;
}
if (elementType->isInterface()) {
@@ -110,17 +113,15 @@
}
std::string VectorType::getJavaType(bool /* forInitializer */) const {
+ const std::string elementJavaType = mElementType->isTemplatedType()
+ ? mElementType->getJavaType()
+ : mElementType->getJavaTypeClass();
- std::string elementJavaType;
- if (mElementType->isArray()) {
- elementJavaType = mElementType->getJavaType();
- } else {
- elementJavaType = mElementType->getJavaWrapperType();
- }
+ return "java.util.ArrayList<" + elementJavaType + ">";
+}
- return "java.util.ArrayList<"
- + elementJavaType
- + ">";
+std::string VectorType::getJavaTypeClass() const {
+ return "java.util.ArrayList";
}
std::string VectorType::getVtsType() const {
@@ -544,14 +545,17 @@
void VectorType::emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const {
- std::string javaType = getJavaType(false /* forInitializer */);
+ const std::string typeName = getJavaType(false /* forInitializer */);
+ const std::string fieldDeclaration = "final " + typeName + " " + fieldName;
- out << "final "
- << javaType
- << " "
- << fieldName
+ emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
+}
+
+void VectorType::emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const {
+ out << declaredFieldName
<< " = new "
- << javaType
+ << getJavaType(false /* forInitializer */)
<< "();\n";
}
@@ -563,13 +567,18 @@
const std::string &fieldName,
const std::string &offset,
bool isReader) const {
+
+ const std::string fieldNameWithCast = isReader
+ ? "(" + getJavaTypeCast(fieldName) + ")"
+ : fieldName;
+
VectorType::EmitJavaFieldReaderWriterForElementType(
out,
depth,
mElementType.get(),
parcelName,
blobName,
- fieldName,
+ fieldNameWithCast,
offset,
isReader);
}
diff --git a/VectorType.h b/VectorType.h
index 6f6ede7..cc889c9 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -43,6 +43,7 @@
bool specifyNamespaces) const override;
std::string getJavaType(bool forInitializer) const override;
+ std::string getJavaTypeClass() const override;
std::string getVtsType() const override;
std::string getVtsValueName() const override;
@@ -101,6 +102,9 @@
void emitJavaFieldInitializer(
Formatter &out, const std::string &fieldName) const override;
+ void emitJavaFieldDefaultInitialValue(
+ Formatter &out, const std::string &declaredFieldName) const override;
+
void emitJavaFieldReaderWriter(
Formatter &out,
size_t depth,
diff --git a/build/hidl_interface.go b/build/hidl_interface.go
index 375c656..9f2be74 100644
--- a/build/hidl_interface.go
+++ b/build/hidl_interface.go
@@ -175,7 +175,7 @@
}
func hidlGenCommand(lang string, roots []string, name *fqName) *string {
- cmd := "$(location hidl-gen) -d $(depfile) -o $(genDir)"
+ cmd := "$(location hidl-gen) -p . -d $(depfile) -o $(genDir)"
cmd += " -L" + lang
cmd += " " + strings.Join(wrap("-r", roots, ""), " ")
cmd += " " + name.string()
@@ -288,11 +288,12 @@
Out: concat(wrap(name.sanitizedDir()+"I", interfaces, ".java"),
wrap(name.sanitizedDir(), i.properties.Types, ".java")),
})
- mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory(true)), &javaProperties{
+ mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProperties{
Name: proptools.StringPtr(name.javaName()),
Owner: i.properties.Owner,
Defaults: []string{"hidl-java-module-defaults"},
No_framework_libs: proptools.BoolPtr(true),
+ Installable: proptools.BoolPtr(true),
Srcs: []string{":" + name.javaSourcesName()},
Static_libs: javaDependencies,
@@ -315,7 +316,7 @@
Srcs: i.properties.Srcs,
Out: []string{name.sanitizedDir() + "Constants.java"},
})
- mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory(true)), &javaProperties{
+ mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProperties{
Name: proptools.StringPtr(name.javaConstantsName()),
Owner: i.properties.Owner,
Defaults: []string{"hidl-java-module-defaults"},
@@ -435,7 +436,7 @@
return nil
}
-var doubleLoadablePackageNames = []string {
+var doubleLoadablePackageNames = []string{
"android.hardware.configstore@",
"android.hardware.graphics.allocator@",
"android.hardware.graphics.bufferqueue@",
diff --git a/build/properties.go b/build/properties.go
index 0798157..e0abcf4 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -56,6 +56,7 @@
Owner *string
Defaults []string
No_framework_libs *bool
+ Installable *bool
Sdk_version *string
Srcs []string
Libs []string