Merge "hidl_test: add expression@1.0 to AndroidTest.xml"
diff --git a/AST.h b/AST.h
index fb5686b..9e627b7 100644
--- a/AST.h
+++ b/AST.h
@@ -123,6 +123,10 @@
     status_t generateCppImplHeader(const std::string& outputPath) const;
     status_t generateCppImplSource(const std::string& outputPath) const;
 
+    status_t generateCppAdapter(const std::string& outputPath) const;
+    status_t generateCppAdapterHeader(const std::string& outputPath) const;
+    status_t generateCppAdapterSource(const std::string& outputPath) const;
+
     status_t generateJava(
             const std::string &outputPath,
             const std::string &limitToType) const;
@@ -167,6 +171,9 @@
 
     Scope* getRootScope();
 
+    static void generateCppPackageInclude(Formatter& out, const FQName& package,
+                                          const std::string& klass);
+
    private:
     const Coordinator *mCoordinator;
     std::string mPath;
@@ -209,11 +216,6 @@
     void getPackageAndVersionComponents(
             std::vector<std::string> *components, bool cpp_compatible) const;
 
-    static void generateCppPackageInclude(
-            Formatter &out,
-            const FQName &package,
-            const std::string &klass);
-
     std::string makeHeaderGuard(const std::string &baseName,
                                 bool indicateGenerated = true) const;
     void enterLeaveNamespace(Formatter &out, bool enter) const;
@@ -252,6 +254,7 @@
                                        const std::string &className,
                                        const Method *method,
                                        const Interface *superInterface) const;
+    void generateAdapterMethod(Formatter& out, const Method* method) const;
 
     void generateFetchSymbol(Formatter &out, const std::string &ifaceName) const;
 
diff --git a/Android.bp b/Android.bp
index 6938c25..9e26f42 100644
--- a/Android.bp
+++ b/Android.bp
@@ -115,6 +115,7 @@
     srcs: [
         "Coordinator.cpp",
         "generateCpp.cpp",
+        "generateCppAdapter.cpp",
         "generateCppImpl.cpp",
         "generateJava.cpp",
         "generateVts.cpp",
diff --git a/Interface.cpp b/Interface.cpp
index c7c7fe5..dac6669 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -679,6 +679,10 @@
     return fqName().getInterfaceBaseName();
 }
 
+std::string Interface::getAdapterName() const {
+    return fqName().getInterfaceAdapterName();
+}
+
 std::string Interface::getProxyName() const {
     return fqName().getInterfaceProxyName();
 }
diff --git a/Interface.h b/Interface.h
index bf22cb5..57dcd9c 100644
--- a/Interface.h
+++ b/Interface.h
@@ -71,6 +71,7 @@
 
     // aliases for corresponding methods in this->fqName()
     std::string getBaseName() const;
+    std::string getAdapterName() const;
     std::string getProxyName() const;
     std::string getStubName() const;
     std::string getPassthroughName() const;
diff --git a/generateCppAdapter.cpp b/generateCppAdapter.cpp
new file mode 100644
index 0000000..7741611
--- /dev/null
+++ b/generateCppAdapter.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AST.h"
+
+#include "Coordinator.h"
+#include "EnumType.h"
+#include "HidlTypeAssertion.h"
+#include "Interface.h"
+#include "Method.h"
+#include "Reference.h"
+#include "ScalarType.h"
+#include "Scope.h"
+
+#include <android-base/logging.h>
+#include <hidl-util/Formatter.h>
+#include <hidl-util/StringHelper.h>
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace android {
+
+status_t AST::generateCppAdapter(const std::string& outputPath) const {
+    status_t err = OK;
+
+    err = generateCppAdapterHeader(outputPath);
+    if (err != OK) return err;
+    err = generateCppAdapterSource(outputPath);
+
+    return err;
+}
+
+status_t AST::generateCppAdapterHeader(const std::string& outputPath) const {
+    if (!AST::isInterface()) {
+        return OK;
+    }
+
+    const std::string klassName = getInterface()->getAdapterName();
+
+    std::string path = outputPath;
+    path.append(mCoordinator->convertPackageRootToPath(mPackage));
+    path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
+    path.append(klassName);
+    path.append(".h");
+
+    CHECK(Coordinator::MakeParentHierarchy(path));
+    FILE* file = fopen(path.c_str(), "w");
+
+    if (file == NULL) {
+        return -errno;
+    }
+
+    Formatter out(file);
+
+    const std::string guard = makeHeaderGuard(klassName, true /* indicateGenerated */);
+
+    out << "#ifndef " << guard << "\n";
+    out << "#define " << guard << "\n\n";
+
+    generateCppPackageInclude(out, mPackage, getInterface()->localName());
+
+    enterLeaveNamespace(out, true /* enter */);
+    out.endl();
+
+    const std::string mockName = getInterface()->fqName().cppName();
+
+    out << "class " << klassName << " : public " << mockName << " ";
+    out.block([&] {
+        out << "public:\n";
+        out << "typedef " << mockName << " Pure;\n";
+
+        out << klassName << "(::android::sp<" << mockName << "> impl);\n";
+
+        generateMethods(out, [&](const Method* method, const Interface* /* interface */) {
+            if (method->isHidlReserved()) {
+                return OK;
+            }
+
+            out << "virtual ";
+            method->generateCppSignature(out);
+            out << " override;\n";
+
+            return OK;
+        });
+        out << "private:\n";
+        out << "::android::sp<" << mockName << "> mImpl;\n";
+
+    }) << ";\n\n";
+
+    enterLeaveNamespace(out, false /* enter */);
+
+    out << "#endif // " << guard << "\n";
+
+    return OK;
+}
+
+status_t AST::generateCppAdapterSource(const std::string& outputPath) const {
+    if (!AST::isInterface()) {
+        return OK;
+    }
+
+    const std::string klassName = getInterface()->getAdapterName();
+
+    std::string path = outputPath;
+    path.append(mCoordinator->convertPackageRootToPath(mPackage));
+    path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
+    path.append(klassName);
+    path.append(".cpp");
+
+    CHECK(Coordinator::MakeParentHierarchy(path));
+    FILE* file = fopen(path.c_str(), "w");
+
+    if (file == NULL) {
+        return -errno;
+    }
+
+    Formatter out(file);
+
+    out << "#include <hidladapter/HidlBinderAdapter.h>\n";
+
+    generateCppPackageInclude(out, mPackage, getInterface()->localName());
+    generateCppPackageInclude(out, mPackage, klassName);
+
+    std::set<FQName> allImportedNames;
+    getAllImportedNames(&allImportedNames);
+    for (const auto& item : allImportedNames) {
+        if (item.name() == "types") {
+            continue;
+        }
+        generateCppPackageInclude(out, item, item.getInterfaceAdapterName());
+    }
+
+    out.endl();
+
+    enterLeaveNamespace(out, true /* enter */);
+    out.endl();
+
+    const std::string mockName = getInterface()->fqName().cppName();
+
+    out << klassName << "::" << klassName << "(::android::sp<" << mockName
+        << "> impl) : mImpl(impl) {}";
+
+    generateMethods(out, [&](const Method* method, const Interface* /* interface */) {
+        generateAdapterMethod(out, method);
+        return OK;
+    });
+
+    enterLeaveNamespace(out, false /* enter */);
+    out.endl();
+
+    return OK;
+}
+
+void AST::generateAdapterMethod(Formatter& out, const Method* method) const {
+    if (method->isHidlReserved()) {
+        return;
+    }
+
+    const auto adapt = [](Formatter& out, const std::string& var, const Type* type) {
+        if (!type->isInterface()) {
+            out << var;
+            return;
+        }
+
+        // TODO(b/66900959): if we are creating the adapter for a 1.1 IFoo
+        // and we are using a method that takes/returns a 1.0 Callback, but
+        // there exists a 1.1 Callback (or other subclass that is depended
+        // on by this module), then wrap with the adapter subclass adapter
+        // IFF that callback is a subclass. However, if the callback
+        // is 1.0 ICallback, then wrap with a 1.0 adapter.
+
+        const Interface* interface = static_cast<const Interface*>(type);
+        out << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>("
+            << interface->fqName().cppName() << "::castFrom("
+            << "::android::hardware::details::adaptWithDefault("
+            << "static_cast<::android::sp<" << interface->fqName().cppName() << ">>(" << var
+            << "), [&] { return new " << interface->fqName().getInterfaceAdapterFqName().cppName()
+            << "(" << var << "); })))";
+    };
+
+    const std::string klassName = getInterface()->getAdapterName();
+
+    method->generateCppSignature(out, klassName);
+    out.block([&] {
+         bool hasCallback = !method->canElideCallback() && !method->results().empty();
+
+         if (hasCallback) {
+             out << method->name() << "_cb _hidl_cb_wrapped = [&](";
+             method->emitCppResultSignature(out);
+             out << ") ";
+             out.block([&] {
+                 out << "return _hidl_cb(\n";
+                 out.indent([&]() {
+                     out.join(method->results().begin(), method->results().end(), ",\n",
+                              [&](auto arg) { adapt(out, arg->name(), arg->get()); });
+                 });
+                 out << ");\n";
+             });
+             out << ";\n";
+         }
+
+         out << "auto _hidl_out = mImpl->" << method->name() << "(\n";
+         out.indent([&]() {
+             out.join(method->args().begin(), method->args().end(), ",\n",
+                      [&](auto arg) { adapt(out, arg->name(), arg->get()); });
+             if (hasCallback) {
+                 if (!method->args().empty()) {
+                     out << ",\n";
+                 }
+                 out << "_hidl_cb_wrapped";
+             }
+         });
+         out << ");\n";
+
+         const auto elidedCallback = method->canElideCallback();
+         if (elidedCallback) {
+             out.sIf("!_hidl_out.isOkUnchecked()", [&] { out << "return _hidl_out;\n"; });
+             out << "return ";
+             adapt(out, "_hidl_out", elidedCallback->get());
+             out << ";\n";
+         } else {
+             out << "return _hidl_out;\n";
+         }
+     }).endl();
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
index 6cd441d..0f970c5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -110,6 +110,15 @@
     if (lang == "c++-impl-sources") {
         return ast->generateCppImplSource(outputDir);
     }
+    if (lang == "c++-adapter") {
+        return ast->generateCppAdapter(outputDir);
+    }
+    if (lang == "c++-adapter-headers") {
+        return ast->generateCppAdapterHeader(outputDir);
+    }
+    if (lang == "c++-adapter-sources") {
+        return ast->generateCppAdapterSource(outputDir);
+    }
     if (lang == "java") {
         return ast->generateJava(outputDir, limitToType);
     }
@@ -719,14 +728,22 @@
     }
 }
 
+enum class LibraryLocation {
+    // NONE,
+    VENDOR,
+    VENDOR_AVAILABLE,
+    VNDK,
+};
+
 static void generateAndroidBpLibSection(
         Formatter &out,
         bool generateVendor,
+        LibraryLocation libraryLocation,
         const FQName &packageFQName,
         const std::string &libraryName,
         const std::string &genSourceName,
         const std::string &genHeaderName,
-        const std::set<FQName> &importedPackagesHierarchy) {
+        std::function<void(void)> generateDependencies) {
 
     // C++ library definition
     out << "cc_library {\n";
@@ -737,20 +754,31 @@
         << "generated_headers: [\"" << genHeaderName << "\"],\n"
         << "export_generated_headers: [\"" << genHeaderName << "\"],\n";
 
-    if (generateVendor) {
+    switch (libraryLocation) {
+    case LibraryLocation::VENDOR: {
         out << "vendor: true,\n";
-    } else {
-        out << "vendor_available: true,\n";
-        if (!generateForTest) {
-            out << "vndk: ";
-            out.block([&]() {
-                out << "enabled: true,\n";
-                if (isSystemProcessSupportedPackage(packageFQName)) {
-                    out << "support_system_process: true,\n";
-                }
-            }) << ",\n";
-        }
+        break;
     }
+    case LibraryLocation::VENDOR_AVAILABLE: {
+        out << "vendor_available: true,\n";
+        break;
+    }
+    case LibraryLocation::VNDK: {
+        out << "vendor_available: true,\n";
+        out << "vndk: ";
+        out.block([&]() {
+            out << "enabled: true,\n";
+            if (isSystemProcessSupportedPackage(packageFQName)) {
+                out << "support_system_process: true,\n";
+            }
+        }) << ",\n";
+        break;
+    }
+    default: {
+        CHECK(false) << "Invalid library type specified in " << __func__;
+    }
+    }
+
     out << "shared_libs: [\n";
 
     out.indent();
@@ -760,7 +788,7 @@
         << "\"liblog\",\n"
         << "\"libutils\",\n"
         << "\"libcutils\",\n";
-    generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
+    generateDependencies();
     out.unindent();
 
     out << "],\n";
@@ -771,7 +799,7 @@
         << "\"libhidltransport\",\n"
         << "\"libhwbinder\",\n"
         << "\"libutils\",\n";
-    generateAndroidBpDependencyList(out, importedPackagesHierarchy, generateVendor);
+    generateDependencies();
     out.unindent();
     out << "],\n";
     out.unindent();
@@ -779,6 +807,77 @@
     out << "}\n";
 }
 
+static status_t generateAdapterMainSource(
+        const FQName & packageFQName,
+        const char* /* hidl_gen */,
+        Coordinator* coordinator,
+        const std::string &outputPath) {
+    const std::string path = outputPath + "main.cpp";
+    CHECK(Coordinator::MakeParentHierarchy(path));
+    FILE *file = fopen(path.c_str(), "w");
+    if (file == NULL) {
+        return -errno;
+    }
+    Formatter out(file);
+
+    std::vector<FQName> packageInterfaces;
+    status_t err =
+        coordinator->appendPackageInterfacesToVector(packageFQName,
+                                                     &packageInterfaces);
+    if (err != OK) {
+        return err;
+    }
+
+    out << "#include <hidladapter/HidlBinderAdapter.h>\n";
+
+    for (auto &interface : packageInterfaces) {
+        if (interface.name() == "types") {
+            continue;
+        }
+        AST::generateCppPackageInclude(out, interface, interface.getInterfaceAdapterName());
+    }
+
+    out << "int main(int argc, char** argv) ";
+    out.block([&] {
+        out << "return ::android::hardware::adapterMain<\n";
+        out.indent();
+        for (auto &interface : packageInterfaces) {
+            if (interface.name() == "types") {
+                continue;
+            }
+            out << interface.getInterfaceAdapterFqName().cppName();
+
+            if (&interface != &packageInterfaces.back()) {
+                out << ",\n";
+            }
+        }
+        out << ">(\"" << packageFQName.string() << "\", argc, argv);\n";
+        out.unindent();
+    }).endl();
+    return OK;
+}
+
+static status_t isTypesOnlyPackage(const FQName &package, Coordinator *coordinator, bool *result) {
+    std::vector<FQName> packageInterfaces;
+
+    status_t err =
+        coordinator->appendPackageInterfacesToVector(package,
+                                                     &packageInterfaces);
+
+    if (err != OK) {
+        *result = false;
+        return err;
+    }
+
+    bool hasInterface = std::any_of(
+        packageInterfaces.begin(),
+        packageInterfaces.end(),
+        [](const FQName& fqName) { return fqName.name() != "types"; });
+
+    *result = !hasInterface;
+    return OK;
+}
+
 static status_t generateAndroidBpForPackage(
         const FQName &packageFQName,
         const char *hidl_gen,
@@ -905,11 +1004,14 @@
         generateAndroidBpLibSection(
             out,
             false /* generateVendor */,
+            (generateForTest ? LibraryLocation::VENDOR_AVAILABLE : LibraryLocation::VNDK),
             packageFQName,
             libraryName,
             genSourceName,
             genHeaderName,
-            importedPackagesHierarchy);
+            [&]() {
+                generateAndroidBpDependencyList(out, importedPackagesHierarchy, false /* generateVendor */);
+            });
 
         // TODO(b/35813011): make all libraries vendor_available
         // Explicitly create '_vendor' copies of libraries so that
@@ -929,14 +1031,131 @@
             generateAndroidBpLibSection(
                 out,
                 true /* generateVendor */,
+                LibraryLocation::VENDOR,
                 packageFQName,
                 libraryName,
                 genSourceName,
                 genHeaderName,
-                importedPackagesHierarchy);
+                [&]() {
+                    generateAndroidBpDependencyList(out, importedPackagesHierarchy, true /* generateVendor */);
+                });
         }
     }
 
+    bool isTypesOnly;
+    err = isTypesOnlyPackage(packageFQName, coordinator, &isTypesOnly);
+    if (err != OK) return err;
+
+    if (isTypesOnly) {
+        return OK;
+    }
+
+    const std::string adapterName = libraryName + "-adapter";
+    const std::string genAdapterName = adapterName + "_genc++";
+    const std::string adapterHelperName = adapterName + "-helper";
+    const std::string genAdapterSourcesName = adapterHelperName + "_genc++";
+    const std::string genAdapterHeadersName = adapterHelperName + "_genc++_headers";
+
+    std::set<FQName> adapterPackages = importedPackagesHierarchy;
+    adapterPackages.insert(packageFQName);
+
+    out.endl();
+    generateAndroidBpGenSection(
+            out,
+            packageFQName,
+            hidl_gen,
+            coordinator,
+            halFilegroupName,
+            genAdapterSourcesName,
+            "c++-adapter-sources",
+            packageInterfaces,
+            adapterPackages,
+            [&pathPrefix](Formatter &out, const FQName &fqName) {
+                if (fqName.name() != "types") {
+                    out << "\"" << pathPrefix << fqName.getInterfaceAdapterName() << ".cpp\",\n";
+                }
+            });
+    generateAndroidBpGenSection(
+            out,
+            packageFQName,
+            hidl_gen,
+            coordinator,
+            halFilegroupName,
+            genAdapterHeadersName,
+            "c++-adapter-headers",
+            packageInterfaces,
+            adapterPackages,
+            [&pathPrefix](Formatter &out, const FQName &fqName) {
+                if (fqName.name() != "types") {
+                    out << "\"" << pathPrefix << fqName.getInterfaceAdapterName() << ".h\",\n";
+                }
+            });
+
+    out.endl();
+
+    generateAndroidBpLibSection(
+        out,
+        false /* generateVendor */,
+        LibraryLocation::VENDOR_AVAILABLE,
+        packageFQName,
+        adapterHelperName,
+        genAdapterSourcesName,
+        genAdapterHeadersName,
+        [&]() {
+            out << "\"libhidladapter\",\n";
+            generateAndroidBpDependencyList(out, adapterPackages, false /* generateVendor */);
+            for (const auto &importedPackage : importedPackagesHierarchy) {
+                if (importedPackage == packageFQName) {
+                    continue;
+                }
+
+                bool isTypesOnly;
+                err = isTypesOnlyPackage(importedPackage, coordinator, &isTypesOnly);
+                if (err != OK) {
+                    return;
+                }
+                if (isTypesOnly) {
+                    continue;
+                }
+
+                out << "\""
+                    << makeLibraryName(importedPackage)
+                    << "-adapter-helper"
+                    << "\",\n";
+            }
+        });
+    if (err != OK) return err;
+
+    out.endl();
+
+    out << "genrule {\n";
+    out.indent();
+    out << "name: \"" << genAdapterName << "\",\n";
+    out << "tools: [\"" << hidl_gen << "\"],\n";
+    out << "cmd: \"$(location " << hidl_gen << ") -o $(genDir)" << " -Lc++-adapter-main ";
+    generatePackagePathsSection(out, coordinator, packageFQName, adapterPackages);
+    out << packageFQName.string() << "\",\n";
+    out << "out: [\"main.cpp\"]";
+    out.unindent();
+    out << "}\n\n";
+
+    out << "cc_test {\n";
+    out.indent();
+    out << "name: \"" << adapterName << "\",\n";
+    out << "shared_libs: [\n";
+    out.indent();
+    out << "\"libhidladapter\",\n";
+    out << "\"libhidlbase\",\n";
+    out << "\"libhidltransport\",\n";
+    out << "\"libutils\",\n";
+    generateAndroidBpDependencyList(out, adapterPackages, false);
+    out << "\"" << adapterHelperName << "\",\n";
+    out.unindent();
+    out << "],\n";
+    out << "generated_sources: [\"" << genAdapterName << "\"],\n";
+    out.unindent();
+    out << "}\n";
+
     return OK;
 }
 
@@ -1216,14 +1435,12 @@
      validateForSource,
      generationFunctionForFileOrPackage("c++")
     },
-
     {"c++-headers",
      "(internal) Generates C++ headers for interface files for talking to HIDL interfaces.",
      OutputHandler::NEEDS_DIR /* mOutputMode */,
      validateForSource,
      generationFunctionForFileOrPackage("c++-headers")
     },
-
     {"c++-sources",
      "(internal) Generates C++ sources for interface files for talking to HIDL interfaces.",
      OutputHandler::NEEDS_DIR /* mOutputMode */,
@@ -1257,6 +1474,31 @@
      generationFunctionForFileOrPackage("c++-impl-sources")
     },
 
+    {"c++-adapter",
+     "Takes a x.(y+n) interface and mocks an x.y interface.",
+     OutputHandler::NEEDS_DIR /* mOutputMode */,
+     validateForSource,
+     generationFunctionForFileOrPackage("c++-adapter")
+    },
+    {"c++-adapter-headers",
+     "c++-adapter but headers only",
+     OutputHandler::NEEDS_DIR /* mOutputMode */,
+     validateForSource,
+     generationFunctionForFileOrPackage("c++-adapter-headers")
+    },
+    {"c++-adapter-sources",
+     "c++-adapter but sources only",
+     OutputHandler::NEEDS_DIR /* mOutputMode */,
+     validateForSource,
+     generationFunctionForFileOrPackage("c++-adapter-sources")
+    },
+    {"c++-adapter-main",
+     "c++-adapter but sources only",
+     OutputHandler::NEEDS_DIR /* mOutputMode */,
+     validateIsPackage,
+     generateAdapterMainSource,
+    },
+
     {"java",
      "(internal) Generates Java library for talking to HIDL interfaces in Java.",
      OutputHandler::NEEDS_DIR /* mOutputMode */,
diff --git a/test/hidl_test/hidl_test_client.cpp b/test/hidl_test/hidl_test_client.cpp
index 96d271c..aa3cded 100644
--- a/test/hidl_test/hidl_test_client.cpp
+++ b/test/hidl_test/hidl_test_client.cpp
@@ -608,6 +608,26 @@
     }
 }
 
+TEST_F(HidlTest, SubInterfaceServiceRegistrationTest) {
+    using ::android::hardware::interfacesEqual;
+
+    const std::string kInstanceName = "no-matter-what-it-is";
+    sp<IChild> child = new SimpleChild();
+    sp<IParent> parent = new SimpleParent();
+
+    EXPECT_EQ(::android::OK, child->registerAsService(kInstanceName));
+
+    EXPECT_TRUE(interfacesEqual(child, IChild::getService(kInstanceName)));
+    EXPECT_TRUE(interfacesEqual(child, IParent::getService(kInstanceName)));
+
+    EXPECT_EQ(::android::OK, parent->registerAsService(kInstanceName));
+
+    // FALSE since passthrough HAL will return an instance
+    // since binderized instance is nullptr
+    EXPECT_FALSE(interfacesEqual(parent, IChild::getService(kInstanceName)));
+    EXPECT_TRUE(interfacesEqual(parent, IParent::getService(kInstanceName)));
+}
+
 // passthrough TODO(b/31959402)
 TEST_F(HidlTest, ServiceParentTest) {
     if (mode == BINDERIZED) {
diff --git a/test/run_all_device_tests.sh b/test/run_all_device_tests.sh
index 3ae7614..4a0feea 100755
--- a/test/run_all_device_tests.sh
+++ b/test/run_all_device_tests.sh
@@ -41,7 +41,7 @@
     done
 
     echo
-    echo ===== SUMMARY =====
+    echo ===== ALL DEVICE TESTS SUMMARY =====
     echo
     if [ ${#FAILED_TESTS[@]} -gt 0 ]; then
         for failed in ${FAILED_TESTS[@]}; do
diff --git a/test/run_all_host_tests.sh b/test/run_all_host_tests.sh
index 0a69a7a..46630a7 100755
--- a/test/run_all_host_tests.sh
+++ b/test/run_all_host_tests.sh
@@ -27,7 +27,7 @@
     done
 
     echo
-    echo ===== SUMMARY =====
+    echo ===== ALL HOST TESTS SUMMARY =====
     echo
     if [ ${#FAILED_TESTS[@]} -gt 0 ]; then
         for failed in ${FAILED_TESTS[@]}; do
diff --git a/test/vendor/1.0/Android.bp b/test/vendor/1.0/Android.bp
index f640216..cff55dc 100644
--- a/test/vendor/1.0/Android.bp
+++ b/test/vendor/1.0/Android.bp
@@ -88,3 +88,81 @@
         "android.hardware.tests.baz@1.0",
     ],
 }
+
+genrule {
+    name: "tests.vendor@1.0-adapter-helper_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.0",
+    srcs: [
+        ":tests.vendor@1.0_hal",
+    ],
+    out: [
+        "tests/vendor/1.0/AVendor.cpp",
+    ],
+}
+
+genrule {
+    name: "tests.vendor@1.0-adapter-helper_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.0",
+    srcs: [
+        ":tests.vendor@1.0_hal",
+    ],
+    out: [
+        "tests/vendor/1.0/AVendor.h",
+    ],
+}
+
+
+cc_library {
+    name: "tests.vendor@1.0-adapter-helper",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["tests.vendor@1.0-adapter-helper_genc++"],
+    generated_headers: ["tests.vendor@1.0-adapter-helper_genc++_headers"],
+    export_generated_headers: ["tests.vendor@1.0-adapter-helper_genc++_headers"],
+    vendor_available: true,
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libhidladapter",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "android.hardware.tests.baz@1.0-adapter-helper",
+        "android.hidl.base@1.0-adapter-helper",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "libhidladapter",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "android.hardware.tests.baz@1.0-adapter-helper",
+        "android.hidl.base@1.0-adapter-helper",
+    ],
+}
+
+genrule {
+    name: "tests.vendor@1.0-adapter_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.0",
+    out: ["main.cpp"]}
+
+cc_test {
+    name: "tests.vendor@1.0-adapter",
+    shared_libs: [
+        "libhidladapter",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "tests.vendor@1.0-adapter-helper",
+    ],
+    generated_sources: ["tests.vendor@1.0-adapter_genc++"],
+}
diff --git a/test/vendor/1.1/Android.bp b/test/vendor/1.1/Android.bp
index 6d41300..8a388d4 100644
--- a/test/vendor/1.1/Android.bp
+++ b/test/vendor/1.1/Android.bp
@@ -88,3 +88,86 @@
         "tests.vendor@1.0_vendor",
     ],
 }
+
+genrule {
+    name: "tests.vendor@1.1-adapter-helper_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.1",
+    srcs: [
+        ":tests.vendor@1.1_hal",
+    ],
+    out: [
+        "tests/vendor/1.1/AVendor.cpp",
+    ],
+}
+
+genrule {
+    name: "tests.vendor@1.1-adapter-helper_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.1",
+    srcs: [
+        ":tests.vendor@1.1_hal",
+    ],
+    out: [
+        "tests/vendor/1.1/AVendor.h",
+    ],
+}
+
+
+cc_library {
+    name: "tests.vendor@1.1-adapter-helper",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["tests.vendor@1.1-adapter-helper_genc++"],
+    generated_headers: ["tests.vendor@1.1-adapter-helper_genc++_headers"],
+    export_generated_headers: ["tests.vendor@1.1-adapter-helper_genc++_headers"],
+    vendor_available: true,
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libhidladapter",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "tests.vendor@1.1",
+        "android.hardware.tests.baz@1.0-adapter-helper",
+        "android.hidl.base@1.0-adapter-helper",
+        "tests.vendor@1.0-adapter-helper",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "libhidladapter",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "tests.vendor@1.1",
+        "android.hardware.tests.baz@1.0-adapter-helper",
+        "android.hidl.base@1.0-adapter-helper",
+        "tests.vendor@1.0-adapter-helper",
+    ],
+}
+
+genrule {
+    name: "tests.vendor@1.1-adapter_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-adapter-main -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport -rtests:system/tools/hidl/test/ tests.vendor@1.1",
+    out: ["main.cpp"]}
+
+cc_test {
+    name: "tests.vendor@1.1-adapter",
+    shared_libs: [
+        "libhidladapter",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.tests.baz@1.0",
+        "tests.vendor@1.0",
+        "tests.vendor@1.1",
+        "tests.vendor@1.1-adapter-helper",
+    ],
+    generated_sources: ["tests.vendor@1.1-adapter_genc++"],
+}
diff --git a/utils/FQName.cpp b/utils/FQName.cpp
index 630fff4..bb62244 100644
--- a/utils/FQName.cpp
+++ b/utils/FQName.cpp
@@ -318,6 +318,10 @@
     return getInterfaceName().substr(1);
 }
 
+std::string FQName::getInterfaceAdapterName() const {
+    return "A" + getInterfaceBaseName();
+}
+
 std::string FQName::getInterfaceHwName() const {
     return "IHw" + getInterfaceBaseName();
 }
@@ -338,6 +342,10 @@
     return FQName(package(), version(), getInterfaceProxyName());
 }
 
+FQName FQName::getInterfaceAdapterFqName() const {
+    return FQName(package(), version(), getInterfaceAdapterName());
+}
+
 FQName FQName::getInterfaceStubFqName() const {
     return FQName(package(), version(), getInterfaceStubName());
 }
diff --git a/utils/include/hidl-util/FQName.h b/utils/include/hidl-util/FQName.h
index 3cdc7a9..ae85238 100644
--- a/utils/include/hidl-util/FQName.h
+++ b/utils/include/hidl-util/FQName.h
@@ -110,6 +110,11 @@
 
     // Must be called on an interface
     // android.hardware.foo@1.0::IBar
+    // -> ABar
+    std::string getInterfaceAdapterName() const;
+
+    // Must be called on an interface
+    // android.hardware.foo@1.0::IBar
     // -> IBar
     std::string getInterfaceName() const;
 
@@ -140,6 +145,11 @@
 
     // Must be called on an interface
     // android.hardware.foo@1.0::IBar
+    // -> android.hardware.foo@1.0::ABar
+    FQName getInterfaceAdapterFqName() const;
+
+    // Must be called on an interface
+    // android.hardware.foo@1.0::IBar
     // -> android.hardware.foo@1.0::BnBar
     FQName getInterfaceStubFqName() const;