cast functions for interfaces.

Test: hidl_test

Bug: 32001926

Change-Id: Ia788d775a668c4232c8a017a6b9430ddf16faca3
diff --git a/generateCpp.cpp b/generateCpp.cpp
index eb6adbe..7f136a0 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -266,6 +266,24 @@
             }
         }
 
+        if (!iface->isRootType()) {
+            out << "// cast static functions\n";
+            std::string childTypeExtra;
+            std::string childTypeResult = iface->getCppResultType(&childTypeExtra);
+            childTypeResult += childTypeExtra;
+
+            for (const Interface *superType : iface->superTypeChain()) {
+                std::string superTypeExtra;
+                out << "static "
+                    << childTypeResult
+                    << " castFrom("
+                    << superType->getCppArgumentType(&superTypeExtra)
+                    << " parent"
+                    << superTypeExtra
+                    << ");\n";
+            }
+        }
+
         out << "\nstatic const ::android::String16 descriptor;\n\n";
 
         out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
@@ -752,13 +770,15 @@
     std::string ifaceName;
     std::string baseName;
 
-    bool isInterface = true;
+    const Interface *iface = nullptr;
+    bool isInterface;
     if (!AST::isInterface(&ifaceName)) {
         baseName = "types";
         isInterface = false;
     } else {
-        const Interface *iface = mRootScope->getInterface();
+        iface = mRootScope->getInterface();
         baseName = iface->getBaseName();
+        isInterface = true;
     }
 
     path.append(baseName);
@@ -792,6 +812,17 @@
         out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
         out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
         out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
+
+        for (const Interface *superType : iface->superTypeChain()) {
+            std::vector<std::string> superPackageComponents;
+            superType->fqName().getPackageAndVersionComponents(&superPackageComponents, false /* cpp_compatible */);
+            std::string superPrefix;
+            for (const auto &component : superPackageComponents) {
+                superPrefix += component;
+                superPrefix += "/";
+            }
+            out << "#include <" << superPrefix << "/Bp" << superType->getBaseName() << ".h>\n";
+        }
     } else {
         out << "#include <" << prefix << "types.h>\n";
     }
@@ -814,6 +845,10 @@
             << iface->fqName().string()
             << "\");\n\n";
 
+        err = generateInterfaceSource(out);
+    }
+
+    if (err == OK && isInterface) {
         err = generateProxySource(out, baseName);
     }
 
@@ -1572,6 +1607,47 @@
     return OK;
 }
 
+status_t AST::generateInterfaceSource(Formatter &out) const {
+    const Interface *iface = mRootScope->getInterface();
+
+    if (!iface->isRootType()) {
+        std::string childTypeExtra;
+        std::string childTypeResult = iface->getCppResultType(&childTypeExtra);
+        childTypeResult += childTypeExtra;
+
+        for (const Interface *superType : iface->superTypeChain()) {
+            std::string superTypeExtra;
+            out << "// static \n"
+                << childTypeResult
+                << " I"
+                << iface->getBaseName()
+                << "::castFrom("
+                << superType->getCppArgumentType(&superTypeExtra)
+                << " parent"
+                << superTypeExtra
+                << ")";
+            out << " {\n";
+            out.indent();
+            out << "return ::android::hardware::castInterface<";
+            out << "I" << iface->getBaseName() << ", "
+                << superType->fqName().cppName() << ", "
+                << "Bp" << iface->getBaseName()
+                << ">(\n";
+            out.indent();
+            out.indent();
+            out << "parent, \""
+                << iface->fqName().string()
+                << "\");\n";
+            out.unindent();
+            out.unindent();
+            out.unindent();
+            out << "}\n\n";
+        }
+    }
+
+    return OK;
+}
+
 status_t AST::generatePassthroughSource(Formatter &out) const {
     const Interface *iface = mRootScope->getInterface();