Enhanced hidl-gen support for generating vts files.
*Support callflow from mehtod annotations.
*Support inheritance for interfaces and types.
*Support Array and Union type.
b/30762234
Change-Id: I059b780d6362a557bb9cfd70d6c5ec0e73916ce3
diff --git a/AST.h b/AST.h
index e2b68cf..d5fe3ba 100644
--- a/AST.h
+++ b/AST.h
@@ -141,9 +141,13 @@
status_t emitTypeDeclarations(Formatter &out) const;
status_t emitJavaTypeDeclarations(Formatter &out) const;
+ status_t emitVtsTypeDeclarations(Formatter &out) const;
- status_t emitVtsTypeDeclarations(
- Formatter &out, const std::vector<Type *> &types) const;
+ // Helper function that generates vts type declaration from the current
+ // AST and the transitive closure of imported ASTs.
+ status_t emitVtsTypeDeclarationsHelper(
+ Formatter &out,
+ std::set<AST*> *allImportSet) const;
DISALLOW_COPY_AND_ASSIGN(AST);
};
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 1c4217c..43e0fd0 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -163,7 +163,7 @@
status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const {
out << "type: TYPE_ARRAY\n" << "vector_value: {\n";
out.indent();
- out << "size: " << mDimension;
+ out << "size: " << mDimension << "\n";
status_t err = mElementType->emitVtsTypeDeclarations(out);
if (err != OK) {
return err;
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 015b576..ce954a1 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -302,34 +302,73 @@
switch (mStyle) {
case STYLE_STRUCT:
{
- out << "type: TYPE_STRUCT\n" << "struct value: {\n";
+ out << "type: TYPE_STRUCT\n";
break;
}
case STYLE_UNION:
{
- out << "type: TYPE_UNION\n" << "union value: {\n";
+ out << "type: TYPE_UNION\n";
break;
}
default:
break;
}
- out.indent();
- // Emit declaration for all subtypes.
- Scope::emitVtsTypeDeclarations(out);
- // Emit declaration for all fields.
- for (const auto &field : *mFields) {
- status_t status = field->type().emitVtsTypeDeclarations(out);
+
+ // Emit declaration for each subtype.
+ for (const auto &type : getSubTypes()) {
+ switch (mStyle) {
+ case STYLE_STRUCT:
+ {
+ out << "struct_value: {\n";
+ break;
+ }
+ case STYLE_UNION:
+ {
+ out << "union_value: {\n";
+ break;
+ }
+ default:
+ break;
+ }
+ out.indent();
+ status_t status(type->emitVtsTypeDeclarations(out));
if (status != OK) {
return status;
}
+ out.unindent();
+ out << "}\n";
}
- out.unindent();
- out << "}\n";
+
+ // Emit declaration for each field.
+ for (const auto &field : *mFields) {
+ switch (mStyle) {
+ case STYLE_STRUCT:
+ {
+ out << "struct_value: {\n";
+ break;
+ }
+ case STYLE_UNION:
+ {
+ out << "union_value: {\n";
+ break;
+ }
+ default:
+ break;
+ }
+ out.indent();
+ out << "name: \"" << field->name() << "\"\n";
+ status_t status = field->type().emitVtsAttributeType(out);
+ if (status != OK) {
+ return status;
+ }
+ out.unindent();
+ out << "}\n";
+ }
return OK;
}
-status_t CompoundType::emitVtsArgumentType(Formatter &out) const {
+status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
switch (mStyle) {
case STYLE_STRUCT:
{
diff --git a/CompoundType.h b/CompoundType.h
index 3628b52..ec60e51 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -50,7 +50,7 @@
bool resultNeedsDeref() const override;
status_t emitVtsTypeDeclarations(Formatter &out) const override;
- status_t emitVtsArgumentType(Formatter &out) const override;
+ status_t emitVtsAttributeType(Formatter &out) const override;
bool isJavaCompatible() const override;
diff --git a/EnumType.cpp b/EnumType.cpp
index 3a9a3c2..05d89f0 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -81,17 +81,7 @@
out.indent();
std::vector<const EnumType *> chain;
- const EnumType *type = this;
- for (;;) {
- chain.push_back(type);
-
- const Type *superType = type->storageType();
- if (superType == NULL || !superType->isEnum()) {
- break;
- }
-
- type = static_cast<const EnumType *>(superType);
- }
+ getTypeChain(&chain);
for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
const auto &type = *it;
@@ -157,17 +147,7 @@
const std::string typeName = scalarType->getJavaType();
std::vector<const EnumType *> chain;
- const EnumType *type = this;
- for (;;) {
- chain.push_back(type);
-
- const Type *superType = type->storageType();
- if (superType == NULL || !superType->isEnum()) {
- break;
- }
-
- type = static_cast<const EnumType *>(superType);
- }
+ getTypeChain(&chain);
for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
const auto &type = *it;
@@ -203,30 +183,52 @@
}
status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
- out << "name: \""
- << localName()
- << "\"\n"
+ out << "name: \"" << localName() << "\"\n"
<< "type: TYPE_ENUM\n"
<< "enum_value: {\n";
out.indent();
- for (const auto &entry : values()) {
- out << "enumerator: \""
- << entry->name()
- << "\"\n"
- << "value: "
- << entry->value()
- << "\n";
+
+ std::vector<const EnumType *> chain;
+ getTypeChain(&chain);
+
+ for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+ const auto &type = *it;
+
+ for (const auto &entry : type->values()) {
+ out << "enumerator: \"" << entry->name() << "\"\n";
+
+ const char *value = entry->value();
+ if (value != NULL) {
+ out << "value: " << value << "\n";
+ }
+ }
}
+
out.unindent();
out << "}\n";
return OK;
}
-status_t EnumType::emitVtsArgumentType(Formatter &out) const {
+status_t EnumType::emitVtsAttributeType(Formatter &out) const {
out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
return OK;
}
+void EnumType::getTypeChain(std::vector<const EnumType *> *out) const {
+ out->clear();
+ const EnumType *type = this;
+ for (;;) {
+ out->push_back(type);
+
+ const Type *superType = type->storageType();
+ if (superType == NULL || !superType->isEnum()) {
+ break;
+ }
+
+ type = static_cast<const EnumType *>(superType);
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
EnumValue::EnumValue(const char *name, const char *value)
diff --git a/EnumType.h b/EnumType.h
index 7aa55e5..7579c7d 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -38,9 +38,10 @@
status_t emitJavaTypeDeclarations(Formatter &out) const override;
status_t emitVtsTypeDeclarations(Formatter &out) const override;
- status_t emitVtsArgumentType(Formatter &out) const override;
+ status_t emitVtsAttributeType(Formatter &out) const override;
private:
+ void getTypeChain(std::vector<const EnumType *> *out) const;
std::vector<EnumValue *> *mValues;
Type *mStorageType;
diff --git a/GenericBinder.cpp b/GenericBinder.cpp
index 6baf538..96f5dc1 100644
--- a/GenericBinder.cpp
+++ b/GenericBinder.cpp
@@ -76,7 +76,7 @@
}
}
-status_t GenericBinder::emitVtsArgumentType(Formatter &) const {
+status_t GenericBinder::emitVtsAttributeType(Formatter &) const {
return UNKNOWN_ERROR;
}
diff --git a/GenericBinder.h b/GenericBinder.h
index c5616f5..7957bde 100644
--- a/GenericBinder.h
+++ b/GenericBinder.h
@@ -28,7 +28,7 @@
const std::string &argName,
bool isReader) const override;
- status_t emitVtsArgumentType(Formatter &out) const override;
+ status_t emitVtsAttributeType(Formatter &out) const override;
};
} // namespace android
diff --git a/Interface.cpp b/Interface.cpp
index 52c1963..c36e75f 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -4,6 +4,8 @@
#include "Formatter.h"
#include "Method.h"
+#include <iostream>
+
namespace android {
Interface::Interface(Interface *super, AnnotationVector *annotations)
@@ -123,7 +125,80 @@
}
}
-status_t Interface::emitVtsArgumentType(Formatter &out) const {
+status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const {
+ for (const auto &type : getSubTypes()) {
+ out << "attribute: {\n";
+ out.indent();
+ status_t status = type->emitVtsTypeDeclarations(out);
+ if (status != OK) {
+ return status;
+ }
+ out.unindent();
+ out << "}\n\n";
+ }
+ return OK;
+}
+
+status_t Interface::emitVtsMethodDeclaration(Formatter &out) const {
+ for (const auto &method : mMethods) {
+ out << "api: {\n";
+ out.indent();
+ out << "name: \"" << method->name() << "\"\n";
+ // Generate declaration for each return value.
+ for (const auto &result : method->results()) {
+ out << "return_type_hidl: {\n";
+ out.indent();
+ status_t status = result->type().emitVtsAttributeType(out);
+ if (status != OK) {
+ return status;
+ }
+ out.unindent();
+ out << "}\n";
+ }
+ // Generate declaration for each input argument
+ for (const auto &arg : method->args()) {
+ out << "arg: {\n";
+ out.indent();
+ status_t status = arg->type().emitVtsAttributeType(out);
+ if (status != OK) {
+ return status;
+ }
+ out.unindent();
+ out << "}\n";
+ }
+ // Generate declaration for each annotation.
+ const AnnotationVector & annotations = method->annotations();
+ for (size_t i = 0; i < annotations.size(); i++) {
+ out << "callflow: {\n";
+ out.indent();
+ std::string name = annotations.keyAt(i);
+ if (name == "entry") {
+ out << "entry: true\n";
+ } else if (name == "exit") {
+ out << "exit: true\n";
+ } else if (name == "callflow") {
+ Annotation* annotation = annotations.valueAt(i);
+ std::vector<std::string> * values = annotation->params()
+ .valueFor("next");
+ for (auto value : *values) {
+ out << "next: " << value << "\n";
+ }
+ } else {
+ std::cerr << "Invalid annotation '"
+ << name << "' for method: " << method->name()
+ << ". Should be one of: entry, exit, callflow. \n";
+ return UNKNOWN_ERROR;
+ }
+ out.unindent();
+ out << "}\n";
+ }
+ out.unindent();
+ out << "}\n\n";
+ }
+ return OK;
+}
+
+status_t Interface::emitVtsAttributeType(Formatter &out) const {
out << "type: TYPE_HIDL_CALLBACK\n"
<< "predefined_type: \""
<< localName()
diff --git a/Interface.h b/Interface.h
index d825122..b46501e 100644
--- a/Interface.h
+++ b/Interface.h
@@ -47,7 +47,10 @@
const std::string &argName,
bool isReader) const override;
- status_t emitVtsArgumentType(Formatter &out) const override;
+ status_t emitVtsAttributeType(Formatter &out) const override;
+
+ status_t emitVtsAttributeDeclaration(Formatter &out) const;
+ status_t emitVtsMethodDeclaration(Formatter &out) const;
bool isJavaCompatible() const override;
diff --git a/Scope.cpp b/Scope.cpp
index 28570e0..c07e9d9 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -112,7 +112,6 @@
return OK;
}
-
const std::vector<Type *> &Scope::getSubTypes() const {
return mTypes;
}
diff --git a/Type.cpp b/Type.cpp
index da45677..907a0c2 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -267,7 +267,7 @@
return OK;
}
-status_t Type::emitVtsArgumentType(Formatter &out) const {
+status_t Type::emitVtsAttributeType(Formatter &out) const {
return emitVtsTypeDeclarations(out);
}
diff --git a/Type.h b/Type.h
index dbb190b..6ee76ca 100644
--- a/Type.h
+++ b/Type.h
@@ -89,8 +89,9 @@
// Generates type declaration for vts proto file.
// TODO (b/30844146): make it a pure virtual method.
virtual status_t emitVtsTypeDeclarations(Formatter &out) const;
- // Generates type declaration as method argument for vts proto file.
- virtual status_t emitVtsArgumentType(Formatter &out) const;
+ // Generates type declaration as attribute of method (return value or method
+ // argument) or attribute of compound type for vts proto file.
+ virtual status_t emitVtsAttributeType(Formatter &out) const;
// Returns true iff this type is supported through the Java backend.
virtual bool isJavaCompatible() const;
diff --git a/VectorType.cpp b/VectorType.cpp
index 44c7e59..e180f22 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -179,6 +179,18 @@
return OK;
}
+status_t VectorType::emitVtsAttributeType(Formatter &out) const {
+ out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
+ out.indent();
+ status_t status = mElementType->emitVtsAttributeType(out);
+ if (status != OK) {
+ return status;
+ }
+ out.unindent();
+ out << "}\n";
+ return OK;
+}
+
bool VectorType::isJavaCompatible() const {
return mElementType->isJavaCompatible();
}
diff --git a/VectorType.h b/VectorType.h
index c4dbd63..9f76314 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -37,6 +37,7 @@
bool resultNeedsDeref() const override;
status_t emitVtsTypeDeclarations(Formatter &out) const override;
+ status_t emitVtsAttributeType(Formatter &out) const override;
bool isJavaCompatible() const override;
diff --git a/generateVts.cpp b/generateVts.cpp
index d1847ba..1a56c1b 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -19,10 +19,33 @@
return out.substr(1, out.size() - 2);
}
-status_t AST::emitVtsTypeDeclarations(
+status_t AST::emitVtsTypeDeclarations(Formatter &out) const {
+ std::set<AST *> allImportedASTs;
+ return emitVtsTypeDeclarationsHelper(out, &allImportedASTs);
+}
+
+status_t AST::emitVtsTypeDeclarationsHelper(
Formatter &out,
- const std::vector<Type *> &types) const {
- for (const auto& type : types) {
+ std::set<AST *> *allImportSet) const {
+ // First, generate vts type declaration for all imported AST.
+ for (const auto &ast : mImportedASTs) {
+ // Already processed, skip.
+ if (allImportSet->find(ast) != allImportSet->end()) {
+ continue;
+ }
+ allImportSet->insert(ast);
+ std::string ifaceName;
+ // We only care about types.hal.
+ if (!ast->isInterface(&ifaceName)) {
+ status_t status = ast->emitVtsTypeDeclarationsHelper(
+ out, allImportSet);
+ if (status != OK) {
+ return status;
+ }
+ }
+ }
+ // Next, generate vts type declaration for the current AST.
+ for (const auto &type : mRootScope->getSubTypes()) {
out << "attribute: {\n";
out.indent();
status_t status = type->emitVtsTypeDeclarations(out);
@@ -98,44 +121,34 @@
out << "interface: {\n";
out.indent();
- status_t status = emitVtsTypeDeclarations(out, iface->getSubTypes());
- if (status != OK) {
- return status;
+ std::vector<const Interface *> chain;
+ while (iface != NULL) {
+ chain.push_back(iface);
+ iface = iface->superType();
}
- for (const auto &method : iface->methods()) {
- out << "api: {\n";
- out.indent();
- out << "name: \"" << method->name() << "\"\n";
- for (const auto &result : method->results()) {
- out << "return_type_hidl: {\n";
- out.indent();
- status_t status = result->type().emitVtsArgumentType(out);
- if (status != OK) {
- return status;
- }
- out.unindent();
- out << "}\n";
+ // Generate all the attribute declarations first.
+ for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+ const Interface *superInterface = *it;
+ status_t status = superInterface->emitVtsAttributeDeclaration(out);
+ if (status != OK) {
+ return status;
}
- for (const auto &arg : method->args()) {
- out << "arg: {\n";
- out.indent();
- status_t status = arg->type().emitVtsArgumentType(out);
- if (status != OK) {
- return status;
- }
- out.unindent();
- out << "}\n";
+ }
+
+ // Generate all the method declarations.
+ for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
+ const Interface *superInterface = *it;
+ status_t status = superInterface->emitVtsMethodDeclaration(out);
+ if (status != OK) {
+ return status;
}
- out.unindent();
- out << "}\n\n";
}
out.unindent();
out << "}\n";
} else {
- status_t status = emitVtsTypeDeclarations(out,
- mRootScope->getSubTypes());
+ status_t status = emitVtsTypeDeclarations(out);
if (status != OK) {
return status;
}
diff --git a/test/data/android/hardware/nfc/1.0/types.vts b/test/data/android/hardware/nfc/1.0/types.vts
index 9645c79..89a3fba 100644
--- a/test/data/android/hardware/nfc/1.0/types.vts
+++ b/test/data/android/hardware/nfc/1.0/types.vts
@@ -46,7 +46,8 @@
attribute: {
name: "nfc_data_t"
type: TYPE_STRUCT
- struct value: {
+ struct_value: {
+ name: "data"
type: TYPE_VECTOR
vector_value: {
type: TYPE_SCALAR