Merge "Install non-core HIDL in system_ext"
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 79d5ee7..82ea179 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -33,29 +33,28 @@
CompoundType::CompoundType(Style style, const std::string& localName, const FQName& fullName,
const Location& location, Scope* parent)
- : Scope(localName, fullName, location, parent), mStyle(style), mFields(nullptr) {}
+ : Scope(localName, fullName, location, parent), mStyle(style) {}
CompoundType::Style CompoundType::style() const {
return mStyle;
}
-void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
- mFields = fields;
+void CompoundType::addField(NamedReference<Type>* field) {
+ mFields.push_back(field);
}
std::vector<const NamedReference<Type>*> CompoundType::getFields() const {
- return mFields ? std::vector<const NamedReference<Type>*>(mFields->begin(), mFields->end())
- : std::vector<const NamedReference<Type>*>();
+ return std::vector<const NamedReference<Type>*>(mFields.begin(), mFields.end());
}
std::vector<const Reference<Type>*> CompoundType::getReferences() const {
std::vector<const Reference<Type>*> ret;
- ret.insert(ret.begin(), mFields->begin(), mFields->end());
+ ret.insert(ret.begin(), mFields.begin(), mFields.end());
return ret;
}
status_t CompoundType::validate() const {
- for (const auto* field : *mFields) {
+ for (const auto* field : mFields) {
const Type& type = field->type();
if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
@@ -79,7 +78,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && mFields->size() < 2) {
+ if (mStyle == STYLE_SAFE_UNION && mFields.size() < 2) {
std::cerr << "ERROR: Safe union must contain at least two types to be useful at "
<< location() << "\n";
return UNKNOWN_ERROR;
@@ -97,7 +96,7 @@
status_t CompoundType::validateUniqueNames() const {
std::unordered_set<std::string> names;
- for (const auto* field : *mFields) {
+ for (const auto* field : mFields) {
if (names.find(field->name()) != names.end()) {
std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
<< field->location() << "\n";
@@ -139,7 +138,7 @@
if (mStyle == STYLE_UNION) {
return false;
}
- for (const auto* field : *mFields) {
+ for (const auto* field : mFields) {
if (!field->get()->canCheckEquality(visited)) {
return false;
}
@@ -203,7 +202,7 @@
}
bool CompoundType::containsInterface() const {
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
if (field->type().isCompoundType()) {
const Type& t = field->type();
const CompoundType* ct = static_cast<const CompoundType*>(&t);
@@ -263,60 +262,45 @@
<< "::hidl_discriminator) _hidl_d_primitive) ";
out.block([&] {
- for (const auto& field : *mFields) {
- out << "case "
- << fullName()
- << "::hidl_discriminator::"
- << field->name()
- << ": ";
+ for (const auto& field : mFields) {
+ out << "case " << fullName() << "::hidl_discriminator::" << field->name()
+ << ": ";
- const std::string tempFieldName = "_hidl_temp_" + field->name();
- out.block([&] {
- if (isReader) {
- out << field->type().getCppResultType()
- << " "
- << tempFieldName
- << ";\n";
+ const std::string tempFieldName = "_hidl_temp_" + field->name();
+ out.block([&] {
+ if (isReader) {
+ out << field->type().getCppResultType() << " " << tempFieldName
+ << ";\n";
- field->type().emitReaderWriter(out, tempFieldName, parcelObj,
- parcelObjIsPointer, isReader, mode);
+ field->type().emitReaderWriter(out, tempFieldName, parcelObj,
+ parcelObjIsPointer, isReader, mode);
- const std::string derefOperator = field->type().resultNeedsDeref()
- ? "*" : "";
- out << name
- << "."
- << field->name()
- << "(std::move("
- << derefOperator
- << tempFieldName
- << "));\n";
- } else {
- const std::string fieldValue = name + "." + field->name() + "()";
- out << field->type().getCppArgumentType()
- << " "
- << tempFieldName
- << " = "
- << fieldValue
- << ";\n";
+ const std::string derefOperator =
+ field->type().resultNeedsDeref() ? "*" : "";
+ out << name << "." << field->name() << "(std::move(" << derefOperator
+ << tempFieldName << "));\n";
+ } else {
+ const std::string fieldValue = name + "." + field->name() + "()";
+ out << field->type().getCppArgumentType() << " " << tempFieldName
+ << " = " << fieldValue << ";\n";
- field->type().emitReaderWriter(out, tempFieldName, parcelObj,
- parcelObjIsPointer, isReader, mode);
- }
- out << "break;\n";
- }).endl();
- }
+ field->type().emitReaderWriter(out, tempFieldName, parcelObj,
+ parcelObjIsPointer, isReader, mode);
+ }
+ out << "break;\n";
+ }).endl();
+ }
- out << "default: ";
- out.block([&] {
- emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive",
- !isReader /*fatal*/);
- if (isReader) {
- out << "_hidl_err = BAD_VALUE;\n";
- handleError(out, mode);
- }
- })
- .endl();
- }).endl();
+ out << "default: ";
+ out.block([&] {
+ emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive",
+ !isReader /*fatal*/);
+ if (isReader) {
+ out << "_hidl_err = BAD_VALUE;\n";
+ handleError(out, mode);
+ }
+ }).endl();
+ }).endl();
}).endl();
}
@@ -339,7 +323,7 @@
return;
}
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
const std::string tempFieldName = "_hidl_temp_" + field->name();
const std::string fieldValue = name + "." + field->name();
@@ -524,8 +508,8 @@
<< " ";
out.block([&] {
- for (size_t idx = 0; idx < mFields->size(); idx++) {
- const auto& field = mFields->at(idx);
+ for (size_t idx = 0; idx < mFields.size(); idx++) {
+ const auto& field = mFields.at(idx);
field->emitDocComment(out);
out << field->name()
@@ -545,7 +529,7 @@
<< definedName() << "& operator=(" << definedName() << "&&);\n" // Move assignment
<< definedName() << "& operator=(const " << definedName() << "&);\n\n"; // Copy assignment
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
// Setter (copy)
out << "void "
<< field->name()
@@ -598,8 +582,7 @@
out << "union hidl_union final {\n";
out.indent();
- for (const auto& field : *mFields) {
-
+ for (const auto& field : mFields) {
size_t fieldAlign, fieldSize;
field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
@@ -656,7 +639,7 @@
out << typeName() << " ";
std::set<FQName> namesDeclaredInScope;
- for (const NamedReference<Type>* ref : *mFields) {
+ for (const NamedReference<Type>* ref : mFields) {
if (ref->definedInline()) {
const Type* type = ref->get();
CHECK(type->isCompoundType()) << " only compound types can be defined inline";
@@ -676,13 +659,13 @@
out.indent([&] {
size_t preDeclaredTypesIdx = 0;
size_t fieldIdx = 0;
- while (preDeclaredTypesIdx < preDeclaredTypes.size() && fieldIdx < mFields->size()) {
+ while (preDeclaredTypesIdx < preDeclaredTypes.size() && fieldIdx < mFields.size()) {
out << "\n";
if (preDeclaredTypes.at(preDeclaredTypesIdx)->location() <
- mFields->at(fieldIdx)->location()) {
+ mFields.at(fieldIdx)->location()) {
preDeclaredTypes.at(preDeclaredTypesIdx++)->emitHidlDefinition(out);
} else {
- emitFieldHidlDefinition(out, *mFields->at(fieldIdx++));
+ emitFieldHidlDefinition(out, *mFields.at(fieldIdx++));
}
}
@@ -691,9 +674,9 @@
preDeclaredTypes.at(preDeclaredTypesIdx++)->emitHidlDefinition(out);
}
- while (fieldIdx < mFields->size()) {
+ while (fieldIdx < mFields.size()) {
out << "\n";
- emitFieldHidlDefinition(out, *mFields->at(fieldIdx++));
+ emitFieldHidlDefinition(out, *mFields.at(fieldIdx++));
}
});
out << "}";
@@ -717,7 +700,7 @@
Scope::emitTypeDeclarations(out);
if (containsPointer()) {
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
field->emitDocComment(out);
out << field->type().getCppStackType()
<< " "
@@ -733,7 +716,7 @@
for (int pass = 0; pass < 2; ++pass) {
size_t offset = 0;
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
size_t fieldAlign, fieldSize;
field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
@@ -794,10 +777,8 @@
void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Scope::emitPackageTypeDeclarations(out);
- out << "static inline std::string toString("
- << getCppArgumentType()
- << (mFields->empty() ? "" : " o")
- << ");\n";
+ out << "static inline std::string toString(" << getCppArgumentType()
+ << (mFields.empty() ? "" : " o") << ");\n";
if (canCheckEquality()) {
out << "static inline bool operator==("
@@ -815,10 +796,8 @@
void CompoundType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
Scope::emitPackageTypeHeaderDefinitions(out);
- out << "static inline std::string toString("
- << getCppArgumentType()
- << (mFields->empty() ? "" : " o")
- << ") ";
+ out << "static inline std::string toString(" << getCppArgumentType()
+ << (mFields.empty() ? "" : " o") << ") ";
out.block([&] {
// include toString for scalar types
@@ -831,7 +810,7 @@
out.indent();
}
- for (const NamedReference<Type>* field : *mFields) {
+ for (const NamedReference<Type>* field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case "
<< fullName()
@@ -850,7 +829,7 @@
}).endl();
} else {
out << "os += \"";
- if (field != *(mFields->begin())) {
+ if (field != *(mFields.begin())) {
out << ", ";
}
out << "." << field->name() << " = \";\n";
@@ -873,9 +852,9 @@
}).endl().endl();
if (canCheckEquality()) {
- out << "static inline bool operator==("
- << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
- << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
+ out << "static inline bool operator==(" << getCppArgumentType() << " "
+ << (mFields.empty() ? "/* lhs */" : "lhs") << ", " << getCppArgumentType() << " "
+ << (mFields.empty() ? "/* rhs */" : "rhs") << ") ";
out.block([&] {
if (mStyle == STYLE_SAFE_UNION) {
out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
@@ -886,7 +865,7 @@
out.indent();
}
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case "
<< fullName()
@@ -1045,41 +1024,35 @@
<< ".hidl_d) ";
out.block([&] {
- for (const auto& field : *mFields) {
- const std::string parameterFieldName = (parameterName + ".hidl_u." +
- field->name());
+ for (const auto& field : mFields) {
+ const std::string parameterFieldName =
+ (parameterName + ".hidl_u." + field->name());
- const std::string argumentName = usesMoveSemantics
- ? ("std::move(" + parameterFieldName + ")")
- : parameterFieldName;
+ const std::string argumentName =
+ usesMoveSemantics ? ("std::move(" + parameterFieldName + ")")
+ : parameterFieldName;
- out << "case hidl_discriminator::"
- << field->name()
- << ": ";
+ out << "case hidl_discriminator::" << field->name() << ": ";
- if (isCopyConstructor) {
- out.block([&] {
- emitSafeUnionFieldConstructor(out, field, argumentName);
- out << "break;\n";
- }).endl();
- } else {
- out.block([&] {
- out << field->name()
- << "("
- << argumentName
- << ");\n"
- << "break;\n";
- }).endl();
- }
- }
+ if (isCopyConstructor) {
+ out.block([&] {
+ emitSafeUnionFieldConstructor(out, field, argumentName);
+ out << "break;\n";
+ }).endl();
+ } else {
+ out.block([&] {
+ out << field->name() << "(" << argumentName << ");\n"
+ << "break;\n";
+ }).endl();
+ }
+ }
- out << "default: ";
- out.block([&] {
- emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d",
- true /*fatal*/);
- })
- .endl();
- }).endl();
+ out << "default: ";
+ out.block([&] {
+ emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d",
+ true /*fatal*/);
+ }).endl();
+ }).endl();
if (isCopyConstructor) {
out << "\nhidl_d = "
@@ -1101,19 +1074,32 @@
<< fullName()
<< ", hidl_d) == 0, \"wrong offset\");\n";
+ const CompoundLayout layout = getCompoundAlignmentAndSize();
+
if (!containsPointer()) {
- CompoundLayout layout = getCompoundAlignmentAndSize();
- out << "static_assert(offsetof("
- << fullName()
- << ", hidl_u) == "
- << layout.innerStruct.offset
- << ", \"wrong offset\");\n";
+ out << "static_assert(offsetof(" << fullName()
+ << ", hidl_u) == " << layout.innerStruct.offset << ", \"wrong offset\");\n";
}
+
out.endl();
- CHECK(!mFields->empty());
- out << "hidl_d = hidl_discriminator::" << mFields->at(0)->name() << ";\n";
- emitSafeUnionFieldConstructor(out, mFields->at(0), "");
+ out << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n";
+
+ // union itself is zero'd when set
+ // padding after descriminator
+ size_t dpad = layout.innerStruct.offset - layout.discriminator.size;
+ emitPaddingZero(out, layout.discriminator.size /*offset*/, dpad /*size*/);
+
+ size_t innerStructEnd = layout.innerStruct.offset + layout.innerStruct.size;
+ // final padding of the struct
+ size_t fpad = layout.overall.size - innerStructEnd;
+ emitPaddingZero(out, innerStructEnd /*offset*/, fpad /*size*/);
+
+ out.endl();
+
+ CHECK(!mFields.empty());
+ out << "hidl_d = hidl_discriminator::" << mFields.at(0)->name() << ";\n";
+ emitSafeUnionFieldConstructor(out, mFields.at(0), "");
}).endl().endl();
// Destructor
@@ -1124,13 +1110,15 @@
}).endl().endl();
// Move constructor
- out << fullName() << "::" << definedName() << "(" << definedName() << "&& other) ";
+ out << fullName() << "::" << definedName() << "(" << definedName()
+ << "&& other) : " << fullName() << "() ";
emitSafeUnionCopyAndAssignDefinition(
out, "other", true /* isCopyConstructor */, true /* usesMoveSemantics */);
// Copy constructor
- out << fullName() << "::" << definedName() << "(const " << definedName() << "& other) ";
+ out << fullName() << "::" << definedName() << "(const " << definedName()
+ << "& other) : " << fullName() << "() ";
emitSafeUnionCopyAndAssignDefinition(
out, "other", true /* isCopyConstructor */, false /* usesMoveSemantics */);
@@ -1159,28 +1147,26 @@
out.block([&] {
out << "switch (hidl_d) ";
out.block([&] {
+ for (const auto& field : mFields) {
+ out << "case hidl_discriminator::" << field->name() << ": ";
- for (const auto& field : *mFields) {
- out << "case hidl_discriminator::"
- << field->name()
- << ": ";
+ out.block([&] {
+ out << "::android::hardware::details::destructElement(&(hidl_u."
+ << field->name() << "));\n"
+ << "break;\n";
+ }).endl();
+ }
- out.block([&] {
- out << "::android::hardware::details::destructElement(&(hidl_u."
- << field->name()
- << "));\n"
- << "break;\n";
- }).endl();
- }
-
- out << "default: ";
- out.block(
- [&] { emitSafeUnionUnknownDiscriminatorError(out, "hidl_d", true /*fatal*/); })
+ out << "default: ";
+ out.block([&] {
+ emitSafeUnionUnknownDiscriminatorError(out, "hidl_d", true /*fatal*/);
+ }).endl();
+ })
+ .endl()
.endl();
- }).endl().endl();
}).endl().endl();
- for (const NamedReference<Type>* field : *mFields) {
+ for (const NamedReference<Type>* field : mFields) {
// Setter (copy)
out << "void "
<< fullName()
@@ -1281,58 +1267,54 @@
if (mStyle == STYLE_SAFE_UNION) {
out << "public " << definedName() << "() ";
out.block([&] {
- CHECK(!mFields->empty());
- mFields->at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
- }).endl().endl();
+ CHECK(!mFields.empty());
+ mFields.at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
+ })
+ .endl()
+ .endl();
const std::string discriminatorStorageType = (
getUnionDiscriminatorType()->getJavaType(false));
out << "public static final class hidl_discriminator ";
out.block([&] {
- for (size_t idx = 0; idx < mFields->size(); idx++) {
- const auto& field = mFields->at(idx);
+ for (size_t idx = 0; idx < mFields.size(); idx++) {
+ const auto& field = mFields.at(idx);
- field->emitDocComment(out);
- out << "public static final "
- << discriminatorStorageType
- << " "
- << field->name()
- << " = "
- << idx
- << "; // "
- << field->type().getJavaType(true /* forInitializer */)
- << "\n";
- }
+ field->emitDocComment(out);
+ out << "public static final " << discriminatorStorageType << " " << field->name()
+ << " = " << idx << "; // "
+ << field->type().getJavaType(true /* forInitializer */) << "\n";
+ }
- out << "\n"
- << "public static final String getName("
- << discriminatorStorageType
- << " value) ";
+ out << "\n"
+ << "public static final String getName(" << discriminatorStorageType
+ << " value) ";
- out.block([&] {
- out << "switch (value) ";
- out.block([&] {
- for (size_t idx = 0; idx < mFields->size(); idx++) {
- const auto& field = mFields->at(idx);
+ out.block([&] {
+ out << "switch (value) ";
+ out.block([&] {
+ for (size_t idx = 0; idx < mFields.size(); idx++) {
+ const auto& field = mFields.at(idx);
- out << "case "
- << idx
- << ": { return \""
- << field->name()
- << "\"; }\n";
- }
- out << "default: { return \"Unknown\"; }\n";
- }).endl();
- }).endl().endl();
+ out << "case " << idx << ": { return \"" << field->name()
+ << "\"; }\n";
+ }
+ out << "default: { return \"Unknown\"; }\n";
+ }).endl();
+ })
+ .endl()
+ .endl();
- out << "private hidl_discriminator() {}\n";
- }).endl().endl();
+ out << "private hidl_discriminator() {}\n";
+ })
+ .endl()
+ .endl();
out << "private " << discriminatorStorageType << " hidl_d = 0;\n";
out << "private Object hidl_o = null;\n";
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
// Setter
out << "public void "
<< field->name()
@@ -1397,7 +1379,7 @@
<< " getDiscriminator() { return hidl_d; }\n\n";
} else {
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
field->emitDocComment(out);
out << "public ";
@@ -1432,7 +1414,7 @@
out << "return false;\n";
}).endl();
} else {
- for (const auto &field : *mFields) {
+ 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()
@@ -1453,7 +1435,7 @@
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.join(mFields.begin(), mFields.end(), ", \n", [&](const auto& field) {
out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
});
}
@@ -1476,7 +1458,7 @@
out.indent();
}
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case hidl_discriminator."
<< field->name()
@@ -1494,7 +1476,7 @@
}
else {
out << "builder.append(\"";
- if (field != *(mFields->begin())) {
+ if (field != *(mFields.begin())) {
out << ", ";
}
out << "." << field->name() << " = \");\n";
@@ -1531,7 +1513,7 @@
out.indent();
}
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case hidl_discriminator."
<< field->name()
@@ -1616,8 +1598,7 @@
}
size_t offset = layout.innerStruct.offset;
- for (const auto& field : *mFields) {
-
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case hidl_discriminator."
<< field->name()
@@ -1669,7 +1650,7 @@
out.indent();
}
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case hidl_discriminator."
<< field->name()
@@ -1750,7 +1731,7 @@
}
size_t offset = layout.innerStruct.offset;
- for (const auto& field : *mFields) {
+ for (const auto& field : mFields) {
if (mStyle == STYLE_SAFE_UNION) {
out << "case hidl_discriminator."
<< field->name()
@@ -1827,7 +1808,7 @@
out.indent();
}
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
if (!field->type().needsEmbeddedReadWrite()) {
continue;
}
@@ -1884,7 +1865,7 @@
return false;
}
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
if (field->type().needsEmbeddedReadWrite()) {
return true;
}
@@ -1931,7 +1912,7 @@
}
// Emit declaration for each field.
- for (const auto &field : *mFields) {
+ for (const auto& field : mFields) {
switch (mStyle) {
case STYLE_STRUCT:
{
@@ -1971,7 +1952,7 @@
return false;
}
- for (const auto* field : *mFields) {
+ for (const auto* field : mFields) {
if (!field->get()->isJavaCompatible(visited)) {
return false;
}
@@ -1981,7 +1962,7 @@
}
bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
- for (const auto* field : *mFields) {
+ for (const auto* field : mFields) {
if (field->get()->containsPointer(visited)) {
return true;
}
@@ -2011,8 +1992,7 @@
innerStruct.offset = discriminator.size;
}
- for (const auto &field : *mFields) {
-
+ for (const auto& field : mFields) {
// Each field is aligned according to its alignment requirement.
// The surrounding structure's alignment is the maximum of its
// fields' aligments.
@@ -2035,20 +2015,35 @@
innerStruct.offset += Layout::getPad(innerStruct.offset,
innerStruct.align);
- overall.size = innerStruct.offset + innerStruct.size;
-
// An empty struct/union still occupies a byte of space in C++.
- if (overall.size == 0) {
- overall.size = 1;
+ if (innerStruct.size == 0) {
+ innerStruct.size = 1;
}
+ overall.size = innerStruct.offset + innerStruct.size;
+
// Pad the overall structure's size
overall.align = std::max(innerStruct.align, discriminator.align);
overall.size += Layout::getPad(overall.size, overall.align);
+ if (mStyle != STYLE_SAFE_UNION) {
+ CHECK(overall.offset == innerStruct.offset) << overall.offset << " " << innerStruct.offset;
+ CHECK(overall.align == innerStruct.align) << overall.align << " " << innerStruct.align;
+ CHECK(overall.size == innerStruct.size) << overall.size << " " << innerStruct.size;
+ }
+
return compoundLayout;
}
+void CompoundType::emitPaddingZero(Formatter& out, size_t offset, size_t size) const {
+ if (size > 0) {
+ out << "::std::memset(reinterpret_cast<uint8_t*>(this) + " << offset << ", 0, " << size
+ << ");\n";
+ } else {
+ out << "// no padding to zero starting at offset " << offset << "\n";
+ }
+}
+
std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
{8, ScalarType::Kind::KIND_UINT8},
@@ -2056,7 +2051,7 @@
{32, ScalarType::Kind::KIND_UINT32},
};
- size_t numFields = mFields->size();
+ size_t numFields = mFields.size();
auto kind = ScalarType::Kind::KIND_UINT64;
for (const auto& scalar : scalars) {
diff --git a/CompoundType.h b/CompoundType.h
index 55968a4..566427c 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -39,7 +39,7 @@
Style style() const;
std::vector<const NamedReference<Type>*> getFields() const;
- void setFields(std::vector<NamedReference<Type>*>* fields);
+ void addField(NamedReference<Type>* field);
bool isCompoundType() const override;
@@ -137,13 +137,17 @@
};
struct CompoundLayout {
+ // Layout of this entire object including metadata.
+ // For struct/union, this is the same as innerStruct.
Layout overall;
+ // Layout of user-specified data
Layout innerStruct;
+ // Layout of discriminator for safe union (otherwise zero)
Layout discriminator;
};
Style mStyle;
- std::vector<NamedReference<Type>*>* mFields;
+ std::vector<NamedReference<Type>*> mFields;
// only emits the struct body. doesn't emit the last ";\n" from the definition
void emitInlineHidlDefinition(Formatter& out) const;
@@ -170,6 +174,7 @@
bool usesMoveSemantics) const;
CompoundLayout getCompoundAlignmentAndSize() const;
+ void emitPaddingZero(Formatter& out, size_t offset, size_t size) const;
void emitSafeUnionReaderWriterForInterfaces(
Formatter &out,
diff --git a/DocComment.cpp b/DocComment.cpp
index 2a1c981..02b7ab7 100644
--- a/DocComment.cpp
+++ b/DocComment.cpp
@@ -73,13 +73,13 @@
break;
}
- out.setLinePrefix(" *");
+ out.pushLinePrefix(" *");
for (const std::string& line : mLines) {
out << (line.empty() ? "" : " ") << line << "\n";
}
- out.unsetLinePrefix();
+ out.popLinePrefix();
out << " */\n";
}
diff --git a/FmqType.cpp b/FmqType.cpp
index fa49928..37d771e 100644
--- a/FmqType.cpp
+++ b/FmqType.cpp
@@ -28,6 +28,10 @@
const std::string& definedName)
: TemplatedType(parent, definedName), mNamespace(nsp), mName(name) {}
+bool FmqType::isFmq() const {
+ return true;
+}
+
std::string FmqType::templatedTypeName() const {
return mName;
}
diff --git a/FmqType.h b/FmqType.h
index 92a7273..7d76546 100644
--- a/FmqType.h
+++ b/FmqType.h
@@ -28,8 +28,9 @@
FmqType(const std::string& nsp, const std::string& name, Scope* parent,
const std::string& definedName);
- std::string fullName() const;
+ bool isFmq() const override;
+ std::string fullName() const;
std::string templatedTypeName() const override;
std::string getCppType(
diff --git a/Interface.cpp b/Interface.cpp
index 5510fec..0029f43 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -386,23 +386,23 @@
{IMPL_INTERFACE,
[](auto &out) {
// getDebugInfo returns N/A for local objects.
- out << "_hidl_cb({ -1 /* pid */, 0 /* ptr */, \n"
- << sArch
- << "});\n"
- << "return ::android::hardware::Void();\n";
+ out << "::android::hidl::base::V1_0::DebugInfo info = {};\n";
+ out << "info.pid = -1;\n";
+ out << "info.ptr = 0;\n";
+ out << "info.arch = \n" << sArch << ";\n";
+ out << "_hidl_cb(info);\n";
+ out << "return ::android::hardware::Void();\n";
}
},
{IMPL_STUB_IMPL,
[](auto &out) {
- out << "_hidl_cb(";
- out.block([&] {
- out << "::android::hardware::details::getPidIfSharable(),\n"
- << "::android::hardware::details::debuggable()"
- << "? reinterpret_cast<uint64_t>(this) : 0 /* ptr */,\n"
- << sArch << "\n";
- });
- out << ");\n"
- << "return ::android::hardware::Void();\n";
+ out << "::android::hidl::base::V1_0::DebugInfo info = {};\n";
+ out << "info.pid = ::android::hardware::details::getPidIfSharable();\n";
+ out << "info.ptr = ::android::hardware::details::debuggable()"
+ << "? reinterpret_cast<uint64_t>(this) : 0;\n";
+ out << "info.arch = \n" << sArch << ";\n";
+ out << "_hidl_cb(info);\n";
+ out << "return ::android::hardware::Void();\n";
}
}
}, /* cppImpl */
diff --git a/Type.cpp b/Type.cpp
index 80bce2a..5873cc0 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -94,6 +94,10 @@
return false;
}
+bool Type::isFmq() const {
+ return false;
+}
+
Type* Type::resolve() {
return const_cast<Type*>(static_cast<const Type*>(this)->resolve());
}
diff --git a/Type.h b/Type.h
index 0ed120b..6ddd11d 100644
--- a/Type.h
+++ b/Type.h
@@ -56,6 +56,7 @@
virtual bool isTemplatedType() const;
virtual bool isTypeDef() const;
virtual bool isVector() const;
+ virtual bool isFmq() const;
// Resolves the type by unwrapping typedefs
Type* resolve();
diff --git a/build/hidl_interface.go b/build/hidl_interface.go
index fa0896b..e94186b 100644
--- a/build/hidl_interface.go
+++ b/build/hidl_interface.go
@@ -605,16 +605,12 @@
Generated_headers: []string{name.headersName()},
Shared_libs: concat(cppDependencies, []string{
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
"libcutils",
}),
Export_shared_lib_headers: concat(cppDependencies, []string{
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"libutils",
}),
Export_generated_headers: []string{name.headersName()},
@@ -706,8 +702,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
},
@@ -716,7 +710,6 @@
}, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
Export_shared_lib_headers: []string{
"libhidlbase",
- "libhidltransport",
},
Export_static_lib_headers: concat([]string{
"libhidladapter",
@@ -741,8 +734,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
},
@@ -886,11 +877,13 @@
}
var doubleLoadablePackageNames = []string{
+ "android.frameworks.bufferhub@1.0",
"android.hardware.cas@1.0",
"android.hardware.cas.native@1.0",
"android.hardware.configstore@",
"android.hardware.drm@1.0",
"android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
"android.hardware.graphics.allocator@",
"android.hardware.graphics.bufferqueue@",
"android.hardware.media@",
@@ -911,7 +904,7 @@
return false
}
-// packages in libhidltransport
+// packages in libhidlbase
var coreDependencyPackageNames = []string{
"android.hidl.base@",
"android.hidl.manager@",
diff --git a/c2hal/Note.cpp b/c2hal/Note.cpp
index 292bb79..bbb841f 100644
--- a/c2hal/Note.cpp
+++ b/c2hal/Note.cpp
@@ -34,7 +34,7 @@
}
void Note::generateSource(Formatter &out) const {
- out.setLinePrefix("//");
+ out.pushLinePrefix("//");
out << "NOTE:\n";
out.indent();
@@ -45,7 +45,7 @@
}
out.unindent();
- out.unsetLinePrefix();
+ out.popLinePrefix();
out << "\n";
}
diff --git a/c2hal/test/Android.bp b/c2hal/test/Android.bp
index 104d405..722d1a8 100644
--- a/c2hal/test/Android.bp
+++ b/c2hal/test/Android.bp
@@ -73,8 +73,6 @@
export_generated_headers: ["c2hal_test_genc++_headers"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
"libcutils",
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 278334d..bad6151 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -144,7 +144,7 @@
generateStubImplMethod(out, baseName, method);
});
- out.setLinePrefix("//");
+ out.pushLinePrefix("//");
out << iface->definedName() << "* ";
generateFetchSymbol(out, iface->definedName());
out << "(const char* /* name */) {\n";
@@ -152,7 +152,7 @@
out << "return new " << baseName << "();\n";
out.unindent();
out << "}\n\n";
- out.unsetLinePrefix();
+ out.popLinePrefix();
out << "} // namespace implementation\n";
enterLeaveNamespace(out, false /* leave */);
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 6ff5cba..2975d12 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -296,7 +296,7 @@
%type<type> named_struct_or_union_declaration named_enum_declaration
%type<type> compound_declaration annotated_compound_declaration
-%type<field> field_declaration commentable_field_declaration
+%type<docCommentable> field_declaration commentable_field_declaration
%type<fields> field_declarations struct_or_union_body
%type<constantExpression> const_expr
%type<enumValue> enum_value commentable_enum_value
@@ -336,6 +336,7 @@
android::Annotation *annotation;
std::vector<android::Annotation *> *annotations;
android::DocComment* docComment;
+ android::DocCommentable* docCommentable;
}
%%
@@ -925,7 +926,6 @@
{
CHECK((*scope)->isCompoundType());
CompoundType *container = static_cast<CompoundType *>(*scope);
- container->setFields($4);
leaveScope(ast, scope);
ast->addScopedType(container, *scope);
@@ -938,15 +938,10 @@
;
field_declarations
- : /* empty */ { $$ = new std::vector<NamedReference<Type>*>; }
+ : /* empty */ { $$ = nullptr; }
| field_declarations commentable_field_declaration
{
- $$ = $1;
-
- // Compound declaration or error
- if ($2 != nullptr) {
- $$->push_back($2);
- }
+ $$ = nullptr;
}
;
@@ -965,14 +960,18 @@
CHECK((*scope)->isCompoundType());
std::string errorMsg;
- auto style = static_cast<CompoundType *>(*scope)->style();
+ CompoundType* compoundType = static_cast<CompoundType *>(*scope);
+ auto style = compoundType->style();
if (!isValidCompoundTypeField(style, $2, &errorMsg)) {
std::cerr << "ERROR: " << errorMsg << " at "
<< @2 << "\n";
YYERROR;
}
- $$ = new NamedReference<Type>($2, *$1, convertYYLoc(@2, ast));
+
+ NamedReference<Type>* field = new NamedReference<Type>($2, *$1, convertYYLoc(@2, ast));
+ compoundType->addField(field);
+ $$ = field;
}
| annotated_compound_declaration ';'
{
@@ -988,8 +987,8 @@
<< @2 << "\n";
YYERROR;
}
- // Returns fields only
- $$ = nullptr;
+
+ $$ = $1;
}
;
@@ -1149,4 +1148,3 @@
const std::string &errstr) {
std::cerr << "ERROR: " << errstr << " at " << where << "\n";
}
-
diff --git a/hidl2aidl/AidlHelper.cpp b/hidl2aidl/AidlHelper.cpp
index ff809e4..5f84450 100644
--- a/hidl2aidl/AidlHelper.cpp
+++ b/hidl2aidl/AidlHelper.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android-base/logging.h>
#include <android-base/strings.h>
#include <hidl-util/FQName.h>
#include <hidl-util/Formatter.h>
@@ -32,6 +33,18 @@
namespace android {
+Formatter* AidlHelper::notesFormatter = nullptr;
+
+Formatter& AidlHelper::notes() {
+ CHECK(notesFormatter != nullptr);
+ return *notesFormatter;
+}
+
+void AidlHelper::setNotes(Formatter* formatter) {
+ CHECK(formatter != nullptr);
+ notesFormatter = formatter;
+}
+
std::string AidlHelper::getAidlName(const FQName& fqName) {
std::vector<std::string> names;
for (const std::string& name : fqName.names()) {
diff --git a/hidl2aidl/AidlHelper.h b/hidl2aidl/AidlHelper.h
index f4457d3..a6301e4 100644
--- a/hidl2aidl/AidlHelper.h
+++ b/hidl2aidl/AidlHelper.h
@@ -48,7 +48,7 @@
static Formatter getFileWithHeader(const NamedType& namedType, const Coordinator& coordinator);
/* Methods for Type */
- static std::string getAidlType(const Type& type);
+ static std::string getAidlType(const Type& type, const FQName& relativeTo);
/* Methods for NamedType */
static void emitAidl(const NamedType& namedType, const Coordinator& coordinator);
@@ -60,6 +60,13 @@
static void emitAidl(const Interface& interface, const Coordinator& coordinator);
// Returns all methods that would exist in an AIDL equivalent interface
static std::vector<const Method*> getUserDefinedMethods(const Interface& interface);
+
+ static Formatter& notes();
+ static void setNotes(Formatter* formatter);
+
+ private:
+ // This is the formatter to use for additional conversion output
+ static Formatter* notesFormatter;
};
} // namespace android
diff --git a/hidl2aidl/AidlInterface.cpp b/hidl2aidl/AidlInterface.cpp
index 66f32ca..e6d6438 100644
--- a/hidl2aidl/AidlInterface.cpp
+++ b/hidl2aidl/AidlInterface.cpp
@@ -16,6 +16,7 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/strings.h>
#include <hidl-util/FQName.h>
#include <hidl-util/Formatter.h>
#include <hidl-util/StringHelper.h>
@@ -24,7 +25,10 @@
#include "AidlHelper.h"
#include "Coordinator.h"
+#include "DocComment.h"
+#include "FormattingConstants.h"
#include "Interface.h"
+#include "Location.h"
#include "Method.h"
#include "NamedType.h"
#include "Reference.h"
@@ -32,11 +36,29 @@
namespace android {
-static void emitAidlMethodParams(Formatter& out, const std::vector<NamedReference<Type>*> args,
- const std::string& prefix) {
- out.join(args.begin(), args.end(), ", ", [&](const NamedReference<Type>* arg) {
- out << prefix << AidlHelper::getAidlType(*arg->get()) << " " << arg->name();
- });
+static void emitAidlMethodParams(WrappedOutput* wrappedOutput,
+ const std::vector<NamedReference<Type>*> args,
+ const std::string& prefix, const std::string& attachToLast,
+ const Interface& iface) {
+ if (args.size() == 0) {
+ *wrappedOutput << attachToLast;
+ return;
+ }
+
+ for (size_t i = 0; i < args.size(); i++) {
+ const NamedReference<Type>* arg = args[i];
+ std::string out =
+ prefix + AidlHelper::getAidlType(*arg->get(), iface.fqName()) + " " + arg->name();
+ wrappedOutput->group([&] {
+ if (i != 0) wrappedOutput->printUnlessWrapped(" ");
+ *wrappedOutput << out;
+ if (i == args.size() - 1) {
+ if (!attachToLast.empty()) *wrappedOutput << attachToLast;
+ } else {
+ *wrappedOutput << ",";
+ }
+ });
+ }
}
std::vector<const Method*> AidlHelper::getUserDefinedMethods(const Interface& interface) {
@@ -96,6 +118,16 @@
}
}
+struct ResultTransformation {
+ enum class TransformType {
+ MOVED, // Moved to the front of the method name
+ REMOVED, // Removed the result
+ };
+
+ std::string resultName;
+ TransformType type;
+};
+
void AidlHelper::emitAidl(const Interface& interface, const Coordinator& coordinator) {
for (const NamedType* type : interface.getSubTypes()) {
emitAidl(*type, coordinator);
@@ -135,14 +167,16 @@
out.join(methodMap.begin(), methodMap.end(), "\n", [&](const auto& pair) {
const Method* method = pair.second.method;
- method->emitDocComment(out);
std::vector<NamedReference<Type>*> results;
+ std::vector<ResultTransformation> transformations;
for (NamedReference<Type>* res : method->results()) {
if (StringHelper::EndsWith(StringHelper::Uppercase(res->name()), "STATUS") ||
StringHelper::EndsWith(StringHelper::Uppercase(res->name()), "ERROR")) {
- out << "// Ignoring result " << res->get()->getJavaType() << " " << res->name()
- << " since AIDL has built in status types.\n";
+ out << "// Ignoring result " << getAidlType(*res->get(), interface.fqName())
+ << " " << res->name() << " since AIDL has built in status types.\n";
+ transformations.emplace_back(ResultTransformation{
+ res->name(), ResultTransformation::TransformType::REMOVED});
} else {
results.push_back(res);
}
@@ -155,26 +189,73 @@
std::string returnType = "void";
if (results.size() == 1) {
- returnType = getAidlType(*results[0]->get());
+ returnType = getAidlType(*results[0]->get(), interface.fqName());
- out << "// Adding return type to method instead of out param "
- << results[0]->get()->getJavaType() << " " << results[0]->name()
- << " since there is only one return value.\n";
+ out << "// Adding return type to method instead of out param " << returnType << " "
+ << results[0]->name() << " since there is only one return value.\n";
+ transformations.emplace_back(ResultTransformation{
+ results[0]->name(), ResultTransformation::TransformType::MOVED});
results.clear();
}
- if (method->isOneway()) out << "oneway ";
- out << returnType << " " << pair.second.name << "(";
- emitAidlMethodParams(out, method->args(), "in ");
+ if (method->getDocComment() != nullptr) {
+ std::vector<std::string> modifiedDocComment;
+ for (const std::string& line : method->getDocComment()->lines()) {
+ std::vector<std::string> tokens = base::Split(line, " ");
+ if (tokens.size() <= 1 || tokens[0] != "@return") {
+ // unimportant line
+ modifiedDocComment.emplace_back(line);
+ continue;
+ }
- // Join these
- if (!results.empty()) {
- // TODO: Emit warning if a primitive is given as a out param.
- if (!method->args().empty()) out << ", ";
- emitAidlMethodParams(out, results, "out ");
+ const std::string& res = tokens[1];
+ bool transformed = false;
+ for (const ResultTransformation& transform : transformations) {
+ if (transform.resultName != res) continue;
+
+ // Some transform was done to it
+ if (transform.type == ResultTransformation::TransformType::MOVED) {
+ // remove the name
+ tokens.erase(++tokens.begin());
+ transformed = true;
+ } else {
+ CHECK(transform.type == ResultTransformation::TransformType::REMOVED);
+ tokens.insert(tokens.begin(), "The following return was removed\n");
+ transformed = true;
+ }
+ }
+
+ if (!transformed) {
+ tokens.erase(tokens.begin());
+ tokens.insert(tokens.begin(), "@param out");
+ }
+
+ modifiedDocComment.emplace_back(base::Join(tokens, " "));
+ }
+
+ DocComment(base::Join(modifiedDocComment, "\n"), HIDL_LOCATION_HERE).emit(out);
}
- out << ");\n";
+ WrappedOutput wrappedOutput(MAX_LINE_LENGTH);
+
+ if (method->isOneway()) wrappedOutput << "oneway ";
+ wrappedOutput << returnType << " " << pair.second.name << "(";
+
+ if (results.empty()) {
+ emitAidlMethodParams(&wrappedOutput, method->args(), /* prefix */ "in ",
+ /* attachToLast */ ");\n", interface);
+ } else {
+ emitAidlMethodParams(&wrappedOutput, method->args(), /* prefix */ "in ",
+ /* attachToLast */ ",", interface);
+ wrappedOutput.printUnlessWrapped(" ");
+
+ // TODO: Emit warning if a primitive is given as a out param.
+ if (!method->args().empty()) out << ", ";
+ emitAidlMethodParams(&wrappedOutput, results, /* prefix */ "out ",
+ /* attachToLast */ ");\n", interface);
+ }
+
+ out << wrappedOutput;
});
});
}
diff --git a/hidl2aidl/AidlNamedType.cpp b/hidl2aidl/AidlNamedType.cpp
index 6bf35ca..63a0373 100644
--- a/hidl2aidl/AidlNamedType.cpp
+++ b/hidl2aidl/AidlNamedType.cpp
@@ -23,14 +23,24 @@
namespace android {
+static void emitConversionNotes(Formatter& out, const NamedType& namedType) {
+ out << "// This is the HIDL definition of " << namedType.fqName().string() << "\n";
+ out.pushLinePrefix("// ");
+ namedType.emitHidlDefinition(out);
+ out.popLinePrefix();
+ out << "\n";
+}
+
static void emitTypeDefAidlDefinition(Formatter& out, const TypeDef& typeDef) {
out << "// Cannot convert typedef " << typeDef.referencedType()->definedName() << " "
<< typeDef.fqName().string() << " since AIDL does not support typedefs.\n";
+ emitConversionNotes(out, typeDef);
}
static void emitEnumAidlDefinition(Formatter& out, const EnumType& enumType) {
out << "// Cannot convert enum " << enumType.fqName().string()
<< " since AIDL does not support enums.\n";
+ emitConversionNotes(out, enumType);
}
static void emitCompoundTypeAidlDefinition(Formatter& out, const CompoundType& compoundType,
@@ -45,12 +55,14 @@
out.block([&] {
for (const NamedReference<Type>* field : compoundType.getFields()) {
field->emitDocComment(out);
- out << AidlHelper::getAidlType(*field->get()) << " " << field->name() << ";\n";
+ out << AidlHelper::getAidlType(*field->get(), compoundType.fqName()) << " "
+ << field->name() << ";\n";
}
});
} else {
out << "{}\n";
- out << "// FIXME: Add union/safe_union implementations";
+ out << "// Cannot convert unions/safe_unions since AIDL does not support them.\n";
+ emitConversionNotes(out, compoundType);
}
out << "\n\n";
}
diff --git a/hidl2aidl/AidlType.cpp b/hidl2aidl/AidlType.cpp
index b982736..6a31e25 100644
--- a/hidl2aidl/AidlType.cpp
+++ b/hidl2aidl/AidlType.cpp
@@ -14,25 +14,43 @@
* limitations under the License.
*/
+#include <hidl-util/FQName.h>
#include <string>
#include "AidlHelper.h"
+#include "FmqType.h"
#include "NamedType.h"
#include "Type.h"
#include "VectorType.h"
namespace android {
-std::string AidlHelper::getAidlType(const Type& type) {
+static std::string getPlaceholderType(const std::string& type) {
+ return "IBinder /* FIXME: " + type + " */";
+}
+
+std::string AidlHelper::getAidlType(const Type& type, const FQName& relativeTo) {
if (type.isVector()) {
const VectorType& vec = static_cast<const VectorType&>(type);
const Type* elementType = vec.getElementType();
// Aidl doesn't support List<*> for C++ and NDK backends
- return AidlHelper::getAidlType(*elementType) + "[]";
+ return getAidlType(*elementType, relativeTo) + "[]";
} else if (type.isNamedType()) {
const NamedType& namedType = static_cast<const NamedType&>(type);
- return AidlHelper::getAidlFQName(namedType.fqName());
+ if (getAidlPackage(relativeTo) == getAidlPackage(namedType.fqName())) {
+ return getAidlName(namedType.fqName());
+ } else {
+ return getAidlFQName(namedType.fqName());
+ }
+ } else if (type.isMemory()) {
+ return getPlaceholderType("memory");
+ } else if (type.isFmq()) {
+ const FmqType& fmq = static_cast<const FmqType&>(type);
+ return getPlaceholderType(fmq.templatedTypeName() + "<" +
+ getAidlType(*fmq.getElementType(), relativeTo) + ">");
+ } else if (type.isPointer()) {
+ return getPlaceholderType("pointer");
} else {
return type.getJavaType();
}
diff --git a/hidl2aidl/main.cpp b/hidl2aidl/main.cpp
index bc9c440..2509a00 100644
--- a/hidl2aidl/main.cpp
+++ b/hidl2aidl/main.cpp
@@ -15,6 +15,7 @@
*/
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <hidl-util/FQName.h>
#include <hidl-util/Formatter.h>
@@ -25,6 +26,7 @@
#include "AST.h"
#include "AidlHelper.h"
#include "Coordinator.h"
+#include "DocComment.h"
using namespace android;
@@ -107,6 +109,27 @@
return result;
}
+static AST* parse(const Coordinator& coordinator, const FQName& target) {
+ AST* ast = coordinator.parse(target);
+ if (ast == nullptr) {
+ std::cerr << "ERROR: Could not parse " << target.name() << ". Aborting." << std::endl;
+ exit(1);
+ }
+
+ if (!ast->getUnhandledComments().empty()) {
+ AidlHelper::notes()
+ << "Unhandled comments from " << target.string()
+ << " follow. Consider using hidl-lint to locate these and fixup as many "
+ << "as possible.\n";
+ for (const DocComment* docComment : ast->getUnhandledComments()) {
+ docComment->emit(AidlHelper::notes());
+ }
+ AidlHelper::notes() << "\n";
+ }
+
+ return ast;
+}
+
int main(int argc, char** argv) {
const char* me = argv[0];
if (argc == 1) {
@@ -208,16 +231,20 @@
}
}
+ // Set up AIDL conversion log
+ std::string aidlPackage = AidlHelper::getAidlPackage(fqName);
+ std::string aidlName = AidlHelper::getAidlName(fqName);
+ Formatter err = coordinator.getFormatter(
+ fqName, Coordinator::Location::DIRECT,
+ base::Join(base::Split(aidlPackage, "."), "/") + "/" +
+ (aidlName.empty() ? "" : (aidlName + "-")) + "conversion.log");
+ AidlHelper::setNotes(&err);
+
std::vector<const NamedType*> namedTypesInPackage;
for (const FQName& target : targets) {
if (target.name() != "types") continue;
- AST* ast = coordinator.parse(target);
- if (ast == nullptr) {
- std::cerr << "ERROR: Could not parse " << target.name() << ". Aborting."
- << std::endl;
- exit(1);
- }
+ AST* ast = parse(coordinator, target);
CHECK(!ast->isInterface());
@@ -240,12 +267,7 @@
for (const FQName& target : targets) {
if (target.name() == "types") continue;
- AST* ast = coordinator.parse(target);
- if (ast == nullptr) {
- std::cerr << "ERROR: Could not parse " << target.name() << ". Aborting."
- << std::endl;
- exit(1);
- }
+ AST* ast = parse(coordinator, target);
const Interface* iface = ast->getInterface();
CHECK(iface);
diff --git a/hidl2aidl/test/1.0/IBar.hal b/hidl2aidl/test/1.0/IBar.hal
index 118ab56..b58f4d1 100644
--- a/hidl2aidl/test/1.0/IBar.hal
+++ b/hidl2aidl/test/1.0/IBar.hal
@@ -24,4 +24,6 @@
};
extraMethod(Inner inner);
+
+ fmqMethod(fmq_sync<bool> sync, fmq_unsync<int32_t> unsync) generates (pointer t);
};
diff --git a/hidl2aidl/test/1.1/IFoo.hal b/hidl2aidl/test/1.1/IFoo.hal
index 0f36fc5..a04cced 100644
--- a/hidl2aidl/test/1.1/IFoo.hal
+++ b/hidl2aidl/test/1.1/IFoo.hal
@@ -27,6 +27,31 @@
// Should take precedence over @1.0::someBar
someBar_1_1(string a);
+ versionTest_(string a);
+ versionTest_two_(string a) generates (bool bl);
+
useStruct() generates (BigStruct type);
useImportedStruct(Outer outer);
+
+ /**
+ * @param mem memory
+ */
+ useMemory(memory mem);
+ shouldImportCorrectTypes() generates (vec<OnlyIn11> lst);
+
+ /**
+ * @return output output
+ */
+ oneOutput() generates (string output);
+
+ /**
+ * @return out1 out
+ * @return out2 out
+ */
+ multipleOutputs() generates (BigStruct out1, BigStruct out2);
+
+ /**
+ * @return status removed
+ */
+ removedOutput() generates (string status);
};
diff --git a/hidl2aidl/test/2.0/IFoo.hal b/hidl2aidl/test/2.0/IFoo.hal
index d3e6ad4..8c2bbad 100644
--- a/hidl2aidl/test/2.0/IFoo.hal
+++ b/hidl2aidl/test/2.0/IFoo.hal
@@ -16,7 +16,11 @@
package hidl2aidl@2.0;
+import @1.0::IFoo;
+
/* This should go into a package called hidl2aidl2 */
interface IFoo {
oneway someFoo(int8_t a);
+
+ shouldImportExternalTypes(@1.0::IFoo foo);
};
diff --git a/hidl2aidl/test/Android.bp b/hidl2aidl/test/Android.bp
index f722f8b..c841947 100644
--- a/hidl2aidl/test/Android.bp
+++ b/hidl2aidl/test/Android.bp
@@ -20,6 +20,7 @@
cmd: "$(location hidl2aidl) -o $(genDir)/ " +
"-rhidl2aidl:system/tools/hidl/hidl2aidl/test " +
"hidl2aidl@1.0 hidl2aidl@2.0",
+ required: ["android.hidl.base@1.0"],
srcs: [
"1.0/IBar.hal",
"1.0/IFoo.hal",
@@ -38,6 +39,7 @@
"hidl2aidl/Outer.aidl",
"hidl2aidl/OuterInner.aidl",
"hidl2aidl/OverrideMe.aidl",
+ // "hidl2aidl/conversion.log",
"hidl2aidl2/IFoo.aidl",
],
}
diff --git a/host_utils/Formatter.cpp b/host_utils/Formatter.cpp
index 24d690c..c801cf7 100644
--- a/host_utils/Formatter.cpp
+++ b/host_utils/Formatter.cpp
@@ -19,6 +19,7 @@
#include <assert.h>
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <string>
#include <vector>
@@ -65,12 +66,12 @@
return (*this) << "}";
}
-void Formatter::setLinePrefix(const std::string &prefix) {
- mLinePrefix = prefix;
+void Formatter::pushLinePrefix(const std::string& prefix) {
+ mLinePrefix.push_back(prefix);
}
-void Formatter::unsetLinePrefix() {
- mLinePrefix = "";
+void Formatter::popLinePrefix() {
+ mLinePrefix.pop_back();
}
Formatter &Formatter::endl() {
@@ -120,14 +121,16 @@
Formatter& Formatter::operator<<(const std::string& out) {
const size_t len = out.length();
size_t start = 0;
+
+ const std::string& prefix = base::Join(mLinePrefix, "");
while (start < len) {
size_t pos = out.find('\n', start);
if (pos == std::string::npos) {
if (mCurrentPosition == 0) {
fprintf(mFile, "%*s", (int)(getIndentation()), "");
- fprintf(mFile, "%s", mLinePrefix.c_str());
- mCurrentPosition = getIndentation() + mLinePrefix.size();
+ fprintf(mFile, "%s", prefix.c_str());
+ mCurrentPosition = getIndentation() + prefix.size();
}
std::string sub = out.substr(start);
@@ -136,10 +139,10 @@
break;
}
- if (mCurrentPosition == 0 && (pos > start || !mLinePrefix.empty())) {
+ if (mCurrentPosition == 0 && (pos > start || !prefix.empty())) {
fprintf(mFile, "%*s", (int)(getIndentation()), "");
- fprintf(mFile, "%s", mLinePrefix.c_str());
- mCurrentPosition = getIndentation() + mLinePrefix.size();
+ fprintf(mFile, "%s", prefix.c_str());
+ mCurrentPosition = getIndentation() + prefix.size();
}
if (pos == start) {
@@ -157,7 +160,12 @@
}
void Formatter::printBlock(const WrappedOutput::Block& block, size_t lineLength) {
- size_t lineStart = mCurrentPosition ?: (getIndentation() + mLinePrefix.size());
+ size_t prefixSize = 0;
+ for (const std::string& prefix : mLinePrefix) {
+ prefixSize += prefix.size();
+ }
+
+ size_t lineStart = mCurrentPosition ?: (getIndentation() + prefixSize);
size_t blockSize = block.computeSize(false);
if (blockSize + lineStart < lineLength) {
block.print(*this, false);
@@ -166,7 +174,7 @@
// Everything will not fit on this line. Try to fit it on the next line.
blockSize = block.computeSize(true);
- if ((blockSize + getIndentation() + mSpacesPerIndent + mLinePrefix.size()) < lineLength) {
+ if ((blockSize + getIndentation() + mSpacesPerIndent + prefixSize) < lineLength) {
*this << "\n";
indent();
diff --git a/host_utils/include/hidl-util/Formatter.h b/host_utils/include/hidl-util/Formatter.h
index 3c0e116..0364bd9 100644
--- a/host_utils/include/hidl-util/Formatter.h
+++ b/host_utils/include/hidl-util/Formatter.h
@@ -171,9 +171,10 @@
// you want to start a // comment block, for example.
// The prefix will be put before the indentation.
// Will be effective the next time cursor is at the start of line.
- void setLinePrefix(const std::string& prefix);
- // Remove the line prefix.
- void unsetLinePrefix();
+ // Adding two prefixes will output them in the order they were added
+ void pushLinePrefix(const std::string& prefix);
+ // Remove the last line prefix.
+ void popLinePrefix();
bool isValid() const;
size_t getIndentation() const;
@@ -187,7 +188,7 @@
size_t mSpacesPerIndent;
size_t mCurrentPosition;
- std::string mLinePrefix;
+ std::vector<std::string> mLinePrefix;
void printBlock(const WrappedOutput::Block& block, size_t lineLength);
void output(const std::string &text) const;
diff --git a/lint/lints/methodDocComment.cpp b/lint/lints/methodDocComment.cpp
index 7f3ff7b..5a90e91 100644
--- a/lint/lints/methodDocComment.cpp
+++ b/lint/lints/methodDocComment.cpp
@@ -34,7 +34,7 @@
// returns true if the line contained a prefix and false otherwise
static bool getFirstWordAfterPrefix(const std::string& str, const std::string& prefix,
std::string* out) {
- std::string line = base::Trim(str);
+ std::string line = str;
if (base::StartsWith(line, prefix)) {
line = StringHelper::LTrim(line, prefix);
diff --git a/lint/lints/oneway.cpp b/lint/lints/oneway.cpp
index 0b372de..fca0e95 100644
--- a/lint/lints/oneway.cpp
+++ b/lint/lints/oneway.cpp
@@ -38,17 +38,13 @@
// This function returns what kind of methods the interface contains
static InterfaceMethodType getInterfaceOnewayType(const Interface& iface,
bool includeParentMethods) {
- // Don't consider IBase since it is always mixed.
- if (iface.isIBase()) {
- return NONE;
- }
-
InterfaceMethodType onewayType = NONE;
const std::vector<Method*>& methods = iface.userDefinedMethods();
if (methods.empty()) {
- CHECK(iface.superType() != nullptr);
- return includeParentMethods ? getInterfaceOnewayType(*iface.superType(), true) : NONE;
+ return (iface.superType() != nullptr && includeParentMethods)
+ ? getInterfaceOnewayType(*iface.superType(), true)
+ : NONE;
}
for (auto method : methods) {
diff --git a/main.cpp b/main.cpp
index 6fd572d..038a2a9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -465,7 +465,7 @@
bool isSystemProcessSupportedPackage(const FQName& fqName) {
// Technically, so is hidl IBase + IServiceManager, but
- // these are part of libhidltransport.
+ // these are part of libhidlbase.
return fqName.inPackage("android.hardware.graphics.common") ||
fqName.inPackage("android.hardware.graphics.mapper") ||
fqName.string() == "android.hardware.renderscript@1.0" ||
@@ -727,7 +727,6 @@
<< "shared_libs: [\n";
out.indent([&] {
out << "\"libhidlbase\",\n"
- << "\"libhidltransport\",\n"
<< "\"libutils\",\n"
<< "\"" << makeLibraryName(packageFQName) << "\",\n";
diff --git a/test/cpp_impl_test/Android.bp b/test/cpp_impl_test/Android.bp
index 0d53fa5..803ab02 100644
--- a/test/cpp_impl_test/Android.bp
+++ b/test/cpp_impl_test/Android.bp
@@ -38,7 +38,6 @@
generated_headers: ["hidl_cpp_impl_test_gen-headers"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.tests.foo@1.0",
],
diff --git a/test/error_test/line_number_doc_comments/1.0/IFoo.hal b/test/error_test/line_number_doc_comments/1.0/IFoo.hal
new file mode 100644
index 0000000..2be328e
--- /dev/null
+++ b/test/error_test/line_number_doc_comments/1.0/IFoo.hal
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.line_number_doc_comments@1.0;
+
+/**
+ * This is a doc comment
+ */
+/*
+ * Different type of comment
+ */
+// Unhandled comment
+interface IFoo {
+ struct A {};
+
+ enum B : uint32_t {
+ C = 2, // bad (A is not an enum)
+ /* more unhandled stuff */
+ /** some more */
+ };
+
+ // The error is on the next line. Should say 35 in the output.
+ foo()
+};
diff --git a/test/error_test/line_number_doc_comments/1.0/required_error b/test/error_test/line_number_doc_comments/1.0/required_error
new file mode 100644
index 0000000..772b903
--- /dev/null
+++ b/test/error_test/line_number_doc_comments/1.0/required_error
@@ -0,0 +1 @@
+IFoo.hal:35.
\ No newline at end of file
diff --git a/test/format_test/1.0/IFoo.hal b/test/format_test/1.0/IFoo.hal
index 90c792a..56b5993 100644
--- a/test/format_test/1.0/IFoo.hal
+++ b/test/format_test/1.0/IFoo.hal
@@ -30,6 +30,9 @@
int32_t c;
} c;
+ /**
+ * This doc comment should show up
+ */
struct Foo {};
Foo b;
diff --git a/test/hidl_test/Android.bp b/test/hidl_test/Android.bp
index 63cce42..fcecd6d 100644
--- a/test/hidl_test/Android.bp
+++ b/test/hidl_test/Android.bp
@@ -10,8 +10,6 @@
"libcutils",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/test/hidl_test/hidl_test_client.cpp b/test/hidl_test/hidl_test_client.cpp
index ac28d22..9f0ec39 100644
--- a/test/hidl_test/hidl_test_client.cpp
+++ b/test/hidl_test/hidl_test_client.cpp
@@ -1689,6 +1689,9 @@
//do nothing, this is expected
}
+ // further calls fail
+ EXPECT_FAIL(dyingBaz->ping());
+
std::unique_lock<std::mutex> lock(recipient->mutex);
recipient->condition.wait_for(lock, std::chrono::milliseconds(100), [&recipient]() {
return recipient->fired;
@@ -1849,31 +1852,44 @@
TEST_F(HidlTest, InvalidTransactionTest) {
using ::android::hardware::tests::bar::V1_0::BnHwBar;
- using ::android::hardware::tests::bar::V1_0::BpHwBar;
using ::android::hardware::IBinder;
using ::android::hardware::Parcel;
- using ::android::status_t;
- using ::android::OK;
+
+ sp<IBinder> binder = ::android::hardware::toBinder(bar);
Parcel request, reply;
- sp<IBinder> binder;
- status_t status = request.writeInterfaceToken(::android::hardware::tests::bar::V1_0::IBar::descriptor);
+ EXPECT_EQ(::android::OK, request.writeInterfaceToken(IBar::descriptor));
+ EXPECT_EQ(::android::UNKNOWN_TRANSACTION, binder->transact(1234, request, &reply));
- EXPECT_EQ(status, OK);
+ EXPECT_OK(bar->ping()); // still works
+}
- if (mode == BINDERIZED) {
- EXPECT_TRUE(bar->isRemote());
- binder = ::android::hardware::toBinder<IBar>(bar);
- } else {
- // For a local test, just wrap the implementation with a BnHwBar
- binder = new BnHwBar(bar);
- }
+TEST_F(HidlTest, EmptyTransactionTest) {
+ using ::android::hardware::IBinder;
+ using ::android::hardware::Parcel;
+ using ::android::hardware::tests::bar::V1_0::BnHwBar;
- status = binder->transact(1234, request, &reply);
+ sp<IBinder> binder = ::android::hardware::toBinder(bar);
- EXPECT_EQ(status, ::android::UNKNOWN_TRANSACTION);
- // Try another call, to make sure nothing is messed up
- EXPECT_OK(bar->thisIsNew());
+ Parcel request, reply;
+ EXPECT_EQ(::android::BAD_TYPE, binder->transact(2 /*someBoolMethod*/, request, &reply));
+
+ EXPECT_OK(bar->ping()); // still works
+}
+
+TEST_F(HidlTest, WrongDescriptorTest) {
+ using ::android::hardware::IBinder;
+ using ::android::hardware::Parcel;
+ using ::android::hardware::tests::bar::V1_0::BnHwBar;
+
+ sp<IBinder> binder = ::android::hardware::toBinder(bar);
+
+ Parcel request, reply;
+ // wrong descriptor
+ EXPECT_EQ(::android::OK, request.writeInterfaceToken("not a real descriptor"));
+ EXPECT_EQ(::android::BAD_TYPE, binder->transact(2 /*someBoolMethod*/, request, &reply));
+
+ EXPECT_OK(bar->ping()); // still works
}
TEST_F(HidlTest, TwowayMethodOnewayEnabledTest) {
@@ -2066,6 +2082,49 @@
}));
}
+template <typename T>
+void testZeroInit(const std::string& header) {
+ uint8_t buf[sizeof(T)];
+ memset(buf, 0xFF, sizeof(buf));
+
+ T* t = new (buf) T;
+
+ for (size_t i = 0; i < sizeof(T); i++) {
+ EXPECT_EQ(0, buf[i]) << header << " at offset: " << i;
+ }
+
+ t->~T();
+ t = nullptr;
+
+ memset(buf, 0xFF, sizeof(buf));
+ t = new (buf) T(T()); // copy constructor
+
+ for (size_t i = 0; i < sizeof(T); i++) {
+ EXPECT_EQ(0, buf[i]) << header << " at offset: " << i;
+ }
+
+ t->~T();
+ t = nullptr;
+
+ memset(buf, 0xFF, sizeof(buf));
+ const T aT = T();
+ t = new (buf) T(std::move(aT)); // move constructor
+
+ for (size_t i = 0; i < sizeof(T); i++) {
+ EXPECT_EQ(0, buf[i]) << header << " at offset: " << i;
+ }
+
+ t->~T();
+ t = nullptr;
+}
+
+TEST_F(HidlTest, SafeUnionUninit) {
+ testZeroInit<SmallSafeUnion>("SmallSafeUnion");
+ testZeroInit<LargeSafeUnion>("LargeSafeUnion");
+ testZeroInit<InterfaceTypeSafeUnion>("InterfaceTypeSafeUnion");
+ testZeroInit<HandleTypeSafeUnion>("HandleTypeSafeUnion");
+}
+
TEST_F(HidlTest, SafeUnionMoveConstructorTest) {
sp<IOtherInterface> otherInterface = new OtherInterface();
ASSERT_EQ(1, otherInterface->getStrongCount());
diff --git a/test/java_test/Android.bp b/test/java_test/Android.bp
index 4f18adf..87654aa 100644
--- a/test/java_test/Android.bp
+++ b/test/java_test/Android.bp
@@ -11,8 +11,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/test/lazy_test/Android.bp b/test/lazy_test/Android.bp
index 8764b30..04acf6f 100644
--- a/test/lazy_test/Android.bp
+++ b/test/lazy_test/Android.bp
@@ -7,9 +7,7 @@
"libbase",
"liblog",
"libhidlbase",
- "libhidltransport",
"libhidlmemory",
- "libhwbinder",
"libutils",
],
}
diff --git a/test/lazy_test/main.cpp b/test/lazy_test/main.cpp
index 7126e85..48512e0 100644
--- a/test/lazy_test/main.cpp
+++ b/test/lazy_test/main.cpp
@@ -23,6 +23,7 @@
#include <unistd.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
@@ -30,8 +31,11 @@
#include <hwbinder/IPCThreadState.h>
using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
using ::android::hardware::IPCThreadState;
using ::android::hidl::base::V1_0::IBase;
+using ::android::hidl::manager::V1_2::IServiceManager;
static std::string gDescriptor;
static std::string gInstance;
@@ -41,12 +45,52 @@
true /*retry*/, false /*getStub*/);
}
+class HidlLazyTest : public ::testing::Test {
+ protected:
+ sp<IServiceManager> manager;
+
+ void SetUp() override {
+ manager = IServiceManager::getService();
+ ASSERT_NE(manager, nullptr);
+
+ ASSERT_FALSE(isServiceRunning()) << "Service '" << gDescriptor << "/" << gInstance
+ << "' is already running. Please ensure this "
+ << "service is implemented as a lazy HAL, then kill all "
+ << "clients of this service and try again.";
+ }
+
+ static constexpr size_t SHUTDOWN_WAIT_TIME = 10;
+ void TearDown() override {
+ std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds before checking that the "
+ << "service has shut down." << std::endl;
+ IPCThreadState::self()->flushCommands();
+ sleep(SHUTDOWN_WAIT_TIME);
+ ASSERT_FALSE(isServiceRunning()) << "Service failed to shutdown.";
+ }
+
+ bool isServiceRunning() {
+ bool isRunning = false;
+ EXPECT_TRUE(
+ manager->listByInterface(gDescriptor,
+ [&isRunning](const hidl_vec<hidl_string>& instanceNames) {
+ for (const hidl_string& name : instanceNames) {
+ if (name == gInstance) {
+ isRunning = true;
+ break;
+ }
+ }
+ })
+ .isOk());
+ return isRunning;
+ }
+};
+
static constexpr size_t NUM_IMMEDIATE_GET_UNGETS = 100;
-TEST(LazyHidl, GetUnget) {
+TEST_F(HidlLazyTest, GetUnget) {
for (size_t i = 0; i < NUM_IMMEDIATE_GET_UNGETS; i++) {
IPCThreadState::self()->flushCommands();
sp<IBase> hal = getHal();
- ASSERT_NE(nullptr, hal.get());
+ ASSERT_NE(hal.get(), nullptr);
EXPECT_TRUE(hal->ping().isOk());
}
}
@@ -69,7 +113,7 @@
std::cout << "Thread waiting " << sleepTime << " while not holding HAL." << std::endl;
sleep(sleepTime);
sp<IBase> hal = getHal();
- ASSERT_NE(nullptr, hal.get());
+ ASSERT_NE(hal.get(), nullptr);
ASSERT_TRUE(hal->ping().isOk());
}
}
@@ -77,7 +121,7 @@
static constexpr size_t NUM_TIMES_GET_UNGET = 5;
static constexpr size_t MAX_WAITING_DURATION = 10;
static constexpr size_t NUM_CONCURRENT_THREADS = 5;
-TEST(LazyHidl, GetWithWaitConcurrent) {
+TEST_F(HidlLazyTest, GetWithWaitConcurrent) {
std::vector<std::vector<size_t>> threadWaitTimes(NUM_CONCURRENT_THREADS);
for (size_t i = 0; i < threadWaitTimes.size(); i++) {
@@ -108,4 +152,4 @@
gInstance = argv[2];
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}