Generate Android.bp files; Convert to Android.bp

Keep generating Android.mk files for java libraries, but move c++ shared
libraries to Android.bp.

Now that we're building these in Soong, we can build hidl_test in Soong
as well.

Bug: 31742855
Test: hardware/interfaces/update-makefiles.sh
Change-Id: Ifd7b6d423971b04b2120b51d63eacfc6b162e25d
diff --git a/main.cpp b/main.cpp
index ae7f6a8..91fc81c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -125,18 +125,17 @@
     return packageFQName.string();
 }
 
-static void generateMakefileSectionForLanguageAndType(
+static void generateMakefileSectionForType(
         Formatter &out,
         Coordinator *coordinator,
         const FQName &packageFQName,
         const FQName &fqName,
-        const char *typeName,
-        bool forJava) {
+        const char *typeName) {
     out << "\n"
         << "\n#"
         << "\n# Build " << fqName.name() << ".hal";
 
-    if (forJava && typeName != nullptr) {
+    if (typeName != nullptr) {
         out << " (" << typeName << ")";
     }
 
@@ -144,15 +143,7 @@
         << "\nGEN := $(intermediates)/"
         << coordinator->convertPackageRootToPath(packageFQName)
         << coordinator->getPackagePath(packageFQName, true /* relative */);
-    if (!forJava) {
-        CHECK(typeName == nullptr);
-
-        if (fqName.name() == "types") {
-            out << "types.cpp";
-        } else {
-            out << fqName.name().substr(1) << "All.cpp";
-        }
-    } else if (typeName == nullptr) {
+    if (typeName == nullptr) {
         out << fqName.name() << ".java";
     } else {
         out << typeName << ".java";
@@ -192,8 +183,7 @@
     out.indent();
     out.indent();
     out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
-        << "\n-L"
-        << (forJava ? "java" : "c++")
+        << "\n-Ljava"
         << " -r"
         << coordinator->getPackageRoot(packageFQName) << ":"
         << coordinator->getPackageRootPath(packageFQName) << " \\\n";
@@ -202,7 +192,7 @@
         << "::"
         << fqName.name();
 
-    if (forJava && typeName != nullptr) {
+    if (typeName != nullptr) {
         out << "." << typeName;
     }
 
@@ -216,15 +206,14 @@
     out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
 }
 
-static void generateMakefileSectionForLanguage(
+static void generateMakefileSection(
         Formatter &out,
         Coordinator *coordinator,
         const FQName &packageFQName,
         const std::vector<FQName> &packageInterfaces,
-        AST *typesAST,
-        bool forJava) {
+        AST *typesAST) {
     for (const auto &fqName : packageInterfaces) {
-        if (forJava && fqName.name() == "types") {
+        if (fqName.name() == "types") {
             CHECK(typesAST != nullptr);
 
             Scope *rootScope = typesAST->scope();
@@ -242,25 +231,23 @@
                     continue;
                 }
 
-                generateMakefileSectionForLanguageAndType(
+                generateMakefileSectionForType(
                         out,
                         coordinator,
                         packageFQName,
                         fqName,
-                        type->localName().c_str(),
-                        forJava);
+                        type->localName().c_str());
             }
 
             continue;
         }
 
-        generateMakefileSectionForLanguageAndType(
+        generateMakefileSectionForType(
                 out,
                 coordinator,
                 packageFQName,
                 fqName,
-                nullptr /* typeName */,
-                forJava);
+                nullptr /* typeName */);
     }
 }
 
@@ -310,6 +297,10 @@
         ast->getImportedPackages(&importedPackages);
     }
 
+    if (!packageIsJavaCompatible) {
+        return OK;
+    }
+
     std::string path =
         coordinator->getPackagePath(packageFQName, false /* relative */);
 
@@ -326,99 +317,63 @@
 
     Formatter out(file);
 
-    out << "LOCAL_PATH := $(call my-dir)\n"
-        << "include $(CLEAR_VARS)\n\n"
-        << "LOCAL_MODULE := "
-        << libraryName
-        << "\n"
-        << "LOCAL_MODULE_CLASS := SHARED_LIBRARIES\n\n"
-        << "intermediates := $(local-generated-sources-dir)\n\n"
-        << "HIDL := $(HOST_OUT_EXECUTABLES)/"
-        << hidl_gen << "$(HOST_EXECUTABLE_SUFFIX)";
+    out << "# This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
+    out << "LOCAL_PATH := $(call my-dir)\n";
 
-    generateMakefileSectionForLanguage(
-            out,
-            coordinator,
-            packageFQName,
-            packageInterfaces,
-            typesAST,
-            false /* forJava */);
+    enum LibraryStyle {
+        LIBRARY_STYLE_REGULAR,
+        LIBRARY_STYLE_STATIC,
+        LIBRARY_STYLE_END,
+    };
 
-    out << "\n"
-        << "\nLOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)"
-        << "\nLOCAL_SHARED_LIBRARIES := \\";
-    out.indent();
-    out << "\nlibhidl \\"
-        << "\nlibhwbinder \\"
-        << "\nlibutils \\"
-        << "\nlibcutils \\";
+    for (int style = LIBRARY_STYLE_REGULAR; style != LIBRARY_STYLE_END;
+            ++style) {
+        const std::string staticSuffix =
+            (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
 
-    for (const auto &importedPackage : importedPackages) {
-        out << "\n" << makeLibraryName(importedPackage) << " \\";
-    }
-    out << "\n";
-    out.unindent();
-    out << "\nLOCAL_MULTILIB := both";
+        out << "\n"
+            << "########################################"
+            << "########################################\n\n";
 
-    out << "\ninclude $(BUILD_SHARED_LIBRARY)\n";
+        out << "include $(CLEAR_VARS)\n"
+            << "LOCAL_MODULE := "
+            << libraryName
+            << "-java"
+            << staticSuffix
+            << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
+            << "intermediates := $(local-generated-sources-dir)\n\n"
+            << "HIDL := $(HOST_OUT_EXECUTABLES)/"
+            << hidl_gen
+            << "$(HOST_EXECUTABLE_SUFFIX)";
 
-    if (packageIsJavaCompatible) {
-        enum LibraryStyle {
-            LIBRARY_STYLE_REGULAR,
-            LIBRARY_STYLE_STATIC,
-            LIBRARY_STYLE_END,
-        };
-
-        for (int style = LIBRARY_STYLE_REGULAR; style != LIBRARY_STYLE_END;
-                ++style) {
-            const std::string staticSuffix =
-                (style == LIBRARY_STYLE_STATIC) ? "-static" : "";
-
+        if (!importedPackages.empty()) {
             out << "\n"
-                << "########################################"
-                << "########################################\n\n";
-
-            out << "include $(CLEAR_VARS)\n"
-                << "LOCAL_MODULE := "
-                << libraryName
-                << "-java"
-                << staticSuffix
-                << "\nLOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
-                << "intermediates := $(local-generated-sources-dir)\n\n"
-                << "HIDL := $(HOST_OUT_EXECUTABLES)/"
-                << hidl_gen
-                << "$(HOST_EXECUTABLE_SUFFIX)";
-
-            if (!importedPackages.empty()) {
-                out << "\n"
-                    << "\nLOCAL_"
-                    << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
-                    << "JAVA_LIBRARIES := \\";
-
-                out.indent();
-                for (const auto &importedPackage : importedPackages) {
-                    out << "\n"
-                        << makeLibraryName(importedPackage)
-                        << "-java"
-                        << staticSuffix
-                        << " \\";
-                }
-                out << "\n";
-                out.unindent();
-            }
-
-            generateMakefileSectionForLanguage(
-                    out,
-                    coordinator,
-                    packageFQName,
-                    packageInterfaces,
-                    typesAST,
-                    true /* forJava */);
-
-            out << "\ninclude $(BUILD_"
+                << "\nLOCAL_"
                 << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
-                << "JAVA_LIBRARY)\n\n";
+                << "JAVA_LIBRARIES := \\";
+
+            out.indent();
+            for (const auto &importedPackage : importedPackages) {
+                out << "\n"
+                    << makeLibraryName(importedPackage)
+                    << "-java"
+                    << staticSuffix
+                    << " \\";
+            }
+            out << "\n";
+            out.unindent();
         }
+
+        generateMakefileSection(
+                out,
+                coordinator,
+                packageFQName,
+                packageInterfaces,
+                typesAST);
+
+        out << "\ninclude $(BUILD_"
+            << ((style == LIBRARY_STYLE_STATIC) ? "STATIC_" : "")
+            << "JAVA_LIBRARY)\n\n";
     }
 
     out << "\n\n"
@@ -448,6 +403,174 @@
     return OutputHandler::PASS_PACKAGE;
 }
 
+static void generateAndroidBpGenSection(
+        Formatter &out,
+        const FQName &packageFQName,
+        const char *hidl_gen,
+        Coordinator *coordinator,
+        const std::string &genName,
+        const char *language,
+        const std::vector<FQName> &packageInterfaces,
+        const std::function<void(Formatter&, const FQName)> outputFn) {
+
+    out << "genrule {\n";
+    out.indent();
+    out << "name: \"" << genName << "\",\n"
+        << "tool: \"" << hidl_gen << "\",\n";
+
+    out << "cmd: \"$tool -o $genDir"
+        << " -L" << language
+        << " -r"
+        << coordinator->getPackageRoot(packageFQName) << ":"
+        << coordinator->getPackageRootPath(packageFQName)
+        << " " << packageFQName.string() << "\",\n";
+
+    out << "srcs: [\n";
+    out.indent();
+    for (const auto &fqName : packageInterfaces) {
+        out << "\"" << fqName.name() << ".hal\",\n";
+    }
+    out.unindent();
+    out << "],\n";
+
+    out << "out: [\n";
+    out.indent();
+    for (const auto &fqName : packageInterfaces) {
+        outputFn(out, fqName);
+    }
+    out.unindent();
+    out << "],\n";
+
+    out.unindent();
+    out << "}\n\n";
+}
+
+static status_t generateAndroidBpForPackage(
+        const FQName &packageFQName,
+        const char *hidl_gen,
+        Coordinator *coordinator,
+        const std::string &) {
+
+    CHECK(packageFQName.isValid() &&
+          !packageFQName.isFullyQualified() &&
+          packageFQName.name().empty());
+
+    std::vector<FQName> packageInterfaces;
+
+    status_t err =
+        coordinator->appendPackageInterfacesToVector(packageFQName,
+                                                     &packageInterfaces);
+
+    if (err != OK) {
+        return err;
+    }
+
+    std::set<FQName> importedPackages;
+    AST *typesAST = nullptr;
+
+    for (const auto &fqName : packageInterfaces) {
+        AST *ast = coordinator->parse(fqName);
+
+        if (ast == NULL) {
+            fprintf(stderr,
+                    "ERROR: Could not parse %s. Aborting.\n",
+                    fqName.string().c_str());
+
+            return UNKNOWN_ERROR;
+        }
+
+        if (fqName.name() == "types") {
+            typesAST = ast;
+        }
+
+        ast->getImportedPackages(&importedPackages);
+    }
+
+    std::string path =
+        coordinator->getPackagePath(packageFQName, false /* relative */);
+
+    path.append("Android.bp");
+
+    CHECK(Coordinator::MakeParentHierarchy(path));
+    FILE *file = fopen(path.c_str(), "w");
+
+    if (file == NULL) {
+        return -errno;
+    }
+
+    const std::string libraryName = makeLibraryName(packageFQName);
+    const std::string genSourceName = libraryName + "_genc++";
+    const std::string genHeaderName = libraryName + "_genc++_headers";
+    const std::string pathPrefix =
+        coordinator->convertPackageRootToPath(packageFQName) +
+        coordinator->getPackagePath(packageFQName, true /* relative */);
+
+    Formatter out(file);
+
+    out << "// This file is autogenerated by hidl-gen. Do not edit manually.\n\n";
+
+    // Rule to generate the C++ source files
+    generateAndroidBpGenSection(
+            out,
+            packageFQName,
+            hidl_gen,
+            coordinator,
+            genSourceName,
+            "c++",
+            packageInterfaces,
+            [&pathPrefix](Formatter &out, const FQName &fqName) {
+                if (fqName.name() == "types") {
+                    out << "\"" << pathPrefix << "types.cpp\",\n";
+                } else {
+                    out << "\"" << pathPrefix << fqName.name().substr(1) << "All.cpp\",\n";
+                }
+            });
+
+    // Rule to generate the C++ header files
+    generateAndroidBpGenSection(
+            out,
+            packageFQName,
+            hidl_gen,
+            coordinator,
+            genHeaderName,
+            "c++",
+            packageInterfaces,
+            [&pathPrefix](Formatter &out, const FQName &fqName) {
+                out << "\"" << pathPrefix << fqName.name() << ".h\",\n";
+                if (fqName.name() != "types") {
+                    out << "\"" << pathPrefix << "IHw" << fqName.name().substr(1) << ".h\",\n";
+                    out << "\"" << pathPrefix << "Bn" << fqName.name().substr(1) << ".h\",\n";
+                    out << "\"" << pathPrefix << "Bp" << fqName.name().substr(1) << ".h\",\n";
+                    out << "\"" << pathPrefix << "Bs" << fqName.name().substr(1) << ".h\",\n";
+                }
+            });
+
+    // C++ library definition
+    out << "cc_library_shared {\n";
+    out.indent();
+    out << "name: \"" << libraryName << "\",\n"
+        << "generated_sources: [\"" << genSourceName << "\"],\n"
+        << "generated_headers: [\"" << genHeaderName << "\"],\n"
+        << "export_generated_headers: [\"" << genHeaderName << "\"],\n"
+        << "shared_libs: [\n";
+
+    out.indent();
+    out << "\"libhidl\",\n"
+        << "\"libhwbinder\",\n"
+        << "\"libutils\",\n"
+        << "\"libcutils\",\n";
+    for (const auto &importedPackage : importedPackages) {
+        out << "\"" << makeLibraryName(importedPackage) << "\",\n";
+    }
+    out.unindent();
+
+    out << "],\n";
+    out.unindent();
+    out << "}\n";
+
+    return OK;
+}
+
 static status_t generateMakefileImplForPackage(
         const FQName &packageFQName,
         const char *,
@@ -649,6 +772,12 @@
      generateMakefileForPackage,
     },
 
+    {"androidbp",
+     false /* mNeedsOutputDir */,
+     validateForMakefile,
+     generateAndroidBpForPackage,
+    },
+
     {"makefile-impl",
      true /* mNeedsOutputDir */,
      validateForMakefile,