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