Fix strong references

Makes strong references to deal with interface corner case explicitly.
Makes hidl-gen to detect a cycle through typedef.

Cycle example:
typedef S A;
struct S {
    A foo;
};

Fixes: 65559985

Test: mma
Test: error test in follow up CL
Change-Id: I132037995c3fc99edfe3e57a1fe84d3c36ca6993
diff --git a/Interface.cpp b/Interface.cpp
index 2e0d931..0fd702c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -486,14 +486,17 @@
     // Interface is a special case as a reference:
     // its definiton must be completed for extension but
     // not necessary for other references.
-    // As interface declaration appears only in global scope and
-    // method declaration appears only in interface, we may assume
-    // that all references in method definitions are acyclic.
 
     std::vector<const Reference<Type>*> ret;
     if (superType() != nullptr) {
         ret.push_back(&mSuperType);
     }
+
+    for (const auto* method : methods()) {
+        const auto& references = method->getStrongReferences();
+        ret.insert(ret.end(), references.begin(), references.end());
+    }
+
     return ret;
 }
 
@@ -982,5 +985,9 @@
     return Scope::isJavaCompatible(visited);
 }
 
+bool Interface::isNeverStrongReference() const {
+    return true;
+}
+
 }  // namespace android
 
diff --git a/Interface.h b/Interface.h
index ae3bc13..bf22cb5 100644
--- a/Interface.h
+++ b/Interface.h
@@ -121,6 +121,8 @@
 
     bool deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const override;
 
+    bool isNeverStrongReference() const override;
+
    private:
     Reference<Type> mSuperType;
 
diff --git a/Method.cpp b/Method.cpp
index 6885881..64a9a65 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -84,6 +84,24 @@
     return ret;
 }
 
+std::vector<Reference<Type>*> Method::getStrongReferences() {
+    const auto& constRet = static_cast<const Method*>(this)->getStrongReferences();
+    std::vector<Reference<Type>*> ret(constRet.size());
+    std::transform(constRet.begin(), constRet.end(), ret.begin(),
+                   [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
+    return ret;
+}
+
+std::vector<const Reference<Type>*> Method::getStrongReferences() const {
+    std::vector<const Reference<Type>*> ret;
+    for (const auto* ref : getReferences()) {
+        if (!ref->shallowGet()->isNeverStrongReference()) {
+            ret.push_back(ref);
+        }
+    }
+    return ret;
+}
+
 std::vector<ConstantExpression*> Method::getConstantExpressions() {
     const auto& constRet = static_cast<const Method*>(this)->getConstantExpressions();
     std::vector<ConstantExpression*> ret(constRet.size());
diff --git a/Method.h b/Method.h
index 79e320d..291ea34 100644
--- a/Method.h
+++ b/Method.h
@@ -70,6 +70,9 @@
     std::vector<Reference<Type>*> getReferences();
     std::vector<const Reference<Type>*> getReferences() const;
 
+    std::vector<Reference<Type>*> getStrongReferences();
+    std::vector<const Reference<Type>*> getStrongReferences() const;
+
     std::vector<ConstantExpression*> getConstantExpressions();
     std::vector<const ConstantExpression*> getConstantExpressions() const;
 
diff --git a/Type.cpp b/Type.cpp
index cbc47fe..92df2e2 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -149,7 +149,13 @@
 }
 
 std::vector<const Reference<Type>*> Type::getStrongReferences() const {
-    return getReferences();
+    std::vector<const Reference<Type>*> ret;
+    for (const auto* ref : getReferences()) {
+        if (!ref->shallowGet()->isNeverStrongReference()) {
+            ret.push_back(ref);
+        }
+    }
+    return ret;
 }
 
 status_t Type::recursivePass(const std::function<status_t(Type*)>& func,
@@ -306,7 +312,8 @@
     // like pointers, vectors, interfaces.
     if (isStrongRef) {
         // Enum storage type and bitfield element type do not appear in output code.
-        if (isEnum() || isBitField()) return OK;
+        // Typedef does not require complete declaration.
+        if (isEnum() || isBitField() || isTypeDef()) return OK;
 
         std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at "
                   << ref.location() << " is not supported.\n"
@@ -770,6 +777,10 @@
     return OK;
 }
 
+bool Type::isNeverStrongReference() const {
+    return false;
+}
+
 ////////////////////////////////////////
 
 TemplatedType::TemplatedType(Scope* parent) : Type(parent) {}
diff --git a/Type.h b/Type.h
index fc01c40..7bc853d 100644
--- a/Type.h
+++ b/Type.h
@@ -300,7 +300,9 @@
 
     virtual status_t emitExportedHeader(Formatter &out, bool forJava) const;
 
-protected:
+    virtual bool isNeverStrongReference() const;
+
+   protected:
     void handleError(Formatter &out, ErrorMode mode) const;
 
     void emitReaderWriterEmbeddedForTypeName(
diff --git a/TypeDef.cpp b/TypeDef.cpp
index 1592778..d0e0c09 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -63,15 +63,6 @@
     return {&mReferencedType};
 }
 
-std::vector<const Reference<Type>*> TypeDef::getStrongReferences() const {
-    // Typedef definition can be cyclic only if
-    // it is referenced by another typedef
-    if (!mReferencedType.shallowGet()->isTypeDef()) {
-        return {};
-    }
-    return {&mReferencedType};
-}
-
 bool TypeDef::needsEmbeddedReadWrite() const {
     CHECK(!"Should not be here");
     return false;
diff --git a/TypeDef.h b/TypeDef.h
index 0e380fa..d383f50 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -42,7 +42,6 @@
     const Type* resolve() const override;
 
     std::vector<const Reference<Type>*> getReferences() const override;
-    std::vector<const Reference<Type>*> getStrongReferences() const override;
 
     status_t emitTypeDeclarations(Formatter &out) const override;