Merge "Revert "Add compile time test to c2hal""
diff --git a/AST.h b/AST.h
index f82a9ba..9a3670c 100644
--- a/AST.h
+++ b/AST.h
@@ -146,6 +146,11 @@
     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) const;
     void enterLeaveNamespace(Formatter &out, bool enter) const;
 
@@ -161,41 +166,26 @@
     status_t generateTypeSource(
             Formatter &out, const std::string &ifaceName) const;
 
-    enum MethodLocation {
-        PROXY_HEADER,
-        STUB_HEADER,
-        IMPL_HEADER,
-        IMPL_SOURCE,
-        PASSTHROUGH_HEADER
-    };
+    // a method, and in which interface is it originally defined.
+    // be careful of the case where method.isHidlReserved(), where interface
+    // is effectively useless.
+    using MethodGenerator = std::function<status_t(const Method *, const Interface *)>;
 
     status_t generateStubImplHeader(const std::string &outputPath) const;
     status_t generateStubImplSource(const std::string &outputPath) const;
 
-    status_t generateMethods(Formatter &out,
-                             const std::string &className,
-                             MethodLocation type,
-                             bool specifyNamespaces) const;
+    status_t generateMethods(Formatter &out, MethodGenerator gen) const;
     status_t generateStubMethod(Formatter &out,
-                                const std::string &className,
-                                const Method *method,
-                                bool specifyNamespaces) const;
-    status_t generateProxyDeclaration(Formatter &out,
-                                      const std::string &className,
-                                      const Method *method,
-                                      bool specifyNamespaces) const;
-    status_t generateStubImplDeclaration(Formatter &out,
-                                         const std::string &className,
-                                         const Method *method,
-                                         bool specifyNamespaces) const;
+                                const Method *method) const;
     status_t generateStubImplMethod(Formatter &out,
                                     const std::string &className,
-                                    const Method *method,
-                                    bool specifyNamespaces) const;
+                                    const Method *method) const;
     status_t generatePassthroughMethod(Formatter &out,
+                                       const Method *method) const;
+    status_t generateProxyMethodSource(Formatter &out,
                                        const std::string &className,
                                        const Method *method,
-                                       bool specifyNamespaces) const;
+                                       const Interface *superInterface) const;
 
     void generateFetchSymbol(Formatter &out, const std::string &ifaceName) const;
 
@@ -221,12 +211,13 @@
         SYNC_CALLBACK_EXIT,
         ASYNC_CALLBACK_ENTRY,
         ASYNC_CALLBACK_EXIT,
+        PASSTHROUGH_ENTRY,
+        PASSTHROUGH_EXIT,
     };
 
     status_t generateCppInstrumentationCall(
             Formatter &out,
             InstrumentationEvent event,
-            const Interface *iface,
             const Method *method) const;
 
     void declareCppReaderLocals(
diff --git a/CompoundType.cpp b/CompoundType.cpp
index eb5d083..870402b 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -758,7 +758,7 @@
 }
 
 status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
-    out << "name: \"" << localName() << "\"\n";
+    out << "name: \"" << fullName() << "\"\n";
     out << "type: " << getVtsType() << "\n";
 
     // Emit declaration for each subtype.
@@ -813,7 +813,7 @@
 
 status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
     out << "type: " << getVtsType() << "\n";
-    out << "predefined_type: \"" << localName() << "\"\n";
+    out << "predefined_type: \"" << fullName() << "\"\n";
     return OK;
 }
 
diff --git a/Coordinator.cpp b/Coordinator.cpp
index 2e17b61..57da8bb 100644
--- a/Coordinator.cpp
+++ b/Coordinator.cpp
@@ -226,8 +226,7 @@
     packagePath.append(packageSuffix.substr(startPos));
     packagePath.append("/");
 
-    CHECK_EQ(fqName.version().find('@'), 0u);
-    packagePath.append(fqName.version().substr(1));
+    packagePath.append(fqName.version());
     packagePath.append("/");
 
     return packagePath;
@@ -296,7 +295,7 @@
 
     for (const auto &fileName : fileNames) {
         FQName subFQName(
-                package.package() + package.version() + "::" + fileName);
+                package.package() + package.atVersion() + "::" + fileName);
 
         if (!subFQName.isValid()) {
             LOG(WARNING)
@@ -304,7 +303,7 @@
                 << fileName
                 << "' in package "
                 << package.package()
-                << package.version();
+                << package.atVersion();
 
             continue;
         }
diff --git a/EnumType.cpp b/EnumType.cpp
index 1905a3e..27c0075 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -295,7 +295,7 @@
 }
 
 status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
-    out << "name: \"" << localName() << "\"\n";
+    out << "name: \"" << fullName() << "\"\n";
     out << "type: " << getVtsType() << "\n";
     out << "enum_value: {\n";
     out.indent();
@@ -334,7 +334,7 @@
 
 status_t EnumType::emitVtsAttributeType(Formatter &out) const {
     out << "type: " << getVtsType() << "\n";
-    out << "predefined_type: \"" << localName() << "\"\n";
+    out << "predefined_type: \"" << fullName() << "\"\n";
     return OK;
 }
 
diff --git a/FQName.cpp b/FQName.cpp
index 0169e0c..df0515c 100644
--- a/FQName.cpp
+++ b/FQName.cpp
@@ -24,18 +24,21 @@
 
 #define RE_COMPONENT    "[a-zA-Z_][a-zA-Z_0-9]*"
 #define RE_PATH         RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
-#define RE_VERSION      "@[0-9]+[.][0-9]+"
+#define RE_MAJOR        "[0-9]+"
+#define RE_MINOR        "[0-9]+"
 
-static const std::regex kRE1("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH ")");
-static const std::regex kRE2("(" RE_VERSION ")::(" RE_PATH ")");
-static const std::regex kRE3("(" RE_PATH ")(" RE_VERSION ")");
+static const std::regex kRE1("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")?::(" RE_PATH ")");
+static const std::regex kRE2("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH ")");
+static const std::regex kRE3("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")");
 static const std::regex kRE4("(" RE_COMPONENT ")([.]" RE_COMPONENT ")+");
 static const std::regex kRE5("(" RE_COMPONENT ")");
 
-static const std::regex kRE6("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH "):(" RE_COMPONENT ")");
-static const std::regex kRE7("(" RE_VERSION ")::(" RE_PATH "):(" RE_COMPONENT ")");
+static const std::regex kRE6("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")?::(" RE_PATH "):(" RE_COMPONENT ")");
+static const std::regex kRE7("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH "):(" RE_COMPONENT ")");
 static const std::regex kRE8("(" RE_PATH "):(" RE_COMPONENT ")");
 
+static const std::regex kREVer("(" RE_MAJOR ")[.](" RE_MINOR ")");
+
 namespace android {
 
 FQName::FQName()
@@ -57,16 +60,17 @@
     : mValid(true),
       mIsIdentifier(false),
       mPackage(package),
-      mVersion(version),
       mName(name),
       mValueName(valueName) {
+    setVersion(version);
 }
 
 FQName::FQName(const FQName& other)
     : mValid(other.mValid),
       mIsIdentifier(other.mIsIdentifier),
       mPackage(other.mPackage),
-      mVersion(other.mVersion),
+      mMajor(other.mMajor),
+      mMinor(other.mMinor),
       mName(other.mName),
       mValueName(other.mValueName) {
 }
@@ -86,7 +90,7 @@
 }
 
 bool FQName::isFullyQualified() const {
-    return !mPackage.empty() && !mVersion.empty() && !mName.empty();
+    return !mPackage.empty() && !version().empty() && !mName.empty();
 }
 
 bool FQName::isValidValueName() const {
@@ -96,46 +100,52 @@
 
 bool FQName::setTo(const std::string &s) {
     mPackage.clear();
-    mVersion.clear();
+    mMajor.clear();
+    mMinor.clear();
     mName.clear();
 
     mValid = true;
 
     std::smatch match;
     if (std::regex_match(s, match, kRE1)) {
+        CHECK_EQ(match.size(), 5u);
+
+        mPackage = match.str(1);
+        mMajor = match.str(2);
+        mMinor = match.str(3);
+        mName = match.str(4);
+    } else if (std::regex_match(s, match, kRE2)) {
+        CHECK_EQ(match.size(), 4u);
+
+        mMajor = match.str(1);
+        mMinor = match.str(2);
+        mName = match.str(3);
+    } else if (std::regex_match(s, match, kRE3)) {
         CHECK_EQ(match.size(), 4u);
 
         mPackage = match.str(1);
-        mVersion = match.str(2);
-        mName = match.str(3);
-    } else if (std::regex_match(s, match, kRE2)) {
-        CHECK_EQ(match.size(), 3u);
-
-        mVersion = match.str(1);
-        mName = match.str(2);
-    } else if (std::regex_match(s, match, kRE3)) {
-        CHECK_EQ(match.size(), 3u);
-
-        mPackage = match.str(1);
-        mVersion = match.str(2);
+        mMajor = match.str(2);
+        mMinor = match.str(3);
     } else if (std::regex_match(s, match, kRE4)) {
         mName = match.str(0);
     } else if (std::regex_match(s, match, kRE5)) {
         mIsIdentifier = true;
         mName = match.str(0);
     } else if (std::regex_match(s, match, kRE6)) {
-        CHECK_EQ(match.size(), 5u);
+        CHECK_EQ(match.size(), 6u);
 
         mPackage = match.str(1);
-        mVersion = match.str(2);
+        mMajor = match.str(2);
+        mMinor = match.str(3);
+        mName = match.str(4);
+        mValueName = match.str(5);
+    } else if (std::regex_match(s, match, kRE7)) {
+        CHECK_EQ(match.size(), 5u);
+
+        mMajor = match.str(1);
+        mMinor = match.str(2);
         mName = match.str(3);
         mValueName = match.str(4);
-    } else if (std::regex_match(s, match, kRE7)) {
-        CHECK_EQ(match.size(), 4u);
-
-        mVersion = match.str(1);
-        mName = match.str(2);
-        mValueName = match.str(3);
     } else if (std::regex_match(s, match, kRE8)) {
         CHECK_EQ(match.size(), 3u);
 
@@ -158,7 +168,33 @@
 }
 
 std::string FQName::version() const {
-    return mVersion;
+    CHECK(mMajor.empty() == mMinor.empty());
+    if (mMajor.empty() && mMinor.empty()) {
+        return "";
+    }
+    return mMajor + "." + mMinor;
+}
+
+std::string FQName::atVersion() const {
+    std::string v = version();
+    return v.empty() ? "" : ("@" + v);
+}
+
+void FQName::setVersion(const std::string &v) {
+    if (v.empty()) {
+        mMajor.clear();
+        mMinor.clear();
+        return;
+    }
+    std::smatch match;
+    if (std::regex_match(v, match, kREVer)) {
+        CHECK_EQ(match.size(), 3u);
+
+        mMajor = match.str(1);
+        mMinor = match.str(2);
+    } else {
+        mValid = false;
+    }
 }
 
 std::string FQName::name() const {
@@ -180,7 +216,7 @@
 }
 
 FQName FQName::typeName() const {
-    return FQName(mPackage, mVersion, mName);
+    return FQName(mPackage, version(), mName);
 }
 
 void FQName::applyDefaults(
@@ -190,8 +226,8 @@
         mPackage = defaultPackage;
     }
 
-    if (mVersion.empty()) {
-        mVersion = defaultVersion;
+    if (version().empty()) {
+        setVersion(defaultVersion);
     }
 }
 
@@ -200,9 +236,9 @@
 
     std::string out;
     out.append(mPackage);
-    out.append(mVersion);
+    out.append(atVersion());
     if (!mName.empty()) {
-        if (!mPackage.empty() || !mVersion.empty()) {
+        if (!mPackage.empty() || !version().empty()) {
             out.append("::");
         }
         out.append(mName);
@@ -252,7 +288,7 @@
         return *this;
     }
 
-    return FQName(mPackage, mVersion, mName.substr(0, idx));
+    return FQName(mPackage, version(), mName.substr(0, idx));
 }
 
 std::string FQName::tokenName() const {
@@ -336,25 +372,11 @@
 }
 
 std::string FQName::getPackageMajorVersion() const {
-    const std::string packageVersion = version();
-    CHECK(packageVersion[0] == '@');
-    const size_t dotPos = packageVersion.find('.');
-    CHECK(dotPos != std::string::npos);
-    return packageVersion.substr(1, dotPos - 1);
+    return mMajor;
 }
 
 std::string FQName::getPackageMinorVersion() const {
-    const std::string packageVersion = version();
-    CHECK(packageVersion[0] == '@');
-    const size_t dotPos = packageVersion.find('.');
-    CHECK(dotPos != std::string::npos);
-    return packageVersion.substr(dotPos + 1);
-}
-
-std::string FQName::getPackageFullVersion() const {
-    const std::string packageVersion = version();
-    CHECK_GT(packageVersion.length(), 1u);
-    return packageVersion.substr(1);
+    return mMinor;
 }
 
 bool FQName::endsWith(const FQName &other) const {
diff --git a/FQName.h b/FQName.h
index 391ba3d..a781157 100644
--- a/FQName.h
+++ b/FQName.h
@@ -47,6 +47,9 @@
             const std::string &defaultVersion);
 
     std::string package() const;
+    // Return version in the form "@1.0" if it is present, otherwise empty string.
+    std::string atVersion() const;
+    // Return version in the form "1.0" if it is present, otherwise empty string.
     std::string version() const;
 
     // The next two methods return the name part of the FQName, that is, the
@@ -147,16 +150,16 @@
 
     std::string getPackageMinorVersion() const;
 
-    // Returns the version of the package by cutting off the leading '@' prefix.
-    std::string getPackageFullVersion() const;
-
 private:
     bool mValid;
     bool mIsIdentifier;
     std::string mPackage;
-    std::string mVersion;
+    std::string mMajor;
+    std::string mMinor;
     std::string mName;
     std::string mValueName;
+
+    void setVersion(const std::string &v);
 };
 
 }  // namespace android
diff --git a/Interface.cpp b/Interface.cpp
index d348101..f03f3aa 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -252,11 +252,21 @@
         out.unindent();
         out << "}\n\n";
     } else {
+        out << "if (" << name << " == nullptr) {\n";
+        out.indent();
+        out << "_hidl_err = ";
+        out << parcelObjDeref
+            << "writeStrongBinder(nullptr);\n";
+        out.unindent();
+        out << "} else {\n";
+        out.indent();
         out << "_hidl_err = "
             << parcelObjDeref
             << "writeStrongBinder("
             << name
             << "->toBinder());\n";
+        out.unindent();
+        out << "}\n";
 
         handleError(out, mode);
     }
diff --git a/Method.h b/Method.h
index 7e711f0..4f5163d 100644
--- a/Method.h
+++ b/Method.h
@@ -62,8 +62,8 @@
     size_t getSerialId() const;
 
     void generateCppSignature(Formatter &out,
-                              const std::string &className,
-                              bool specifyNamespaces) const;
+                              const std::string &className = "",
+                              bool specifyNamespaces = true) const;
 
     static std::string GetArgSignature(const std::vector<TypedVar *> &args,
                                        bool specifyNamespaces);
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 69ded55..fdc5f90 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -78,6 +78,25 @@
     return guard;
 }
 
+// static
+void AST::generateCppPackageInclude(
+        Formatter &out,
+        const FQName &package,
+        const std::string &klass) {
+
+    out << "#include <";
+
+    std::vector<std::string> components;
+    package.getPackageAndVersionComponents(&components, false /* cpp_compatible */);
+
+    for (const auto &component : components) {
+        out << component << "/";
+    }
+
+    out << klass
+        << ".h>\n";
+}
+
 void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
     std::vector<std::string> packageComponents;
     getPackageAndVersionComponents(
@@ -130,18 +149,7 @@
     out << "#define " << guard << "\n\n";
 
     for (const auto &item : mImportedNames) {
-        out << "#include <";
-
-        std::vector<std::string> components;
-        item.getPackageAndVersionComponents(
-                &components, false /* cpp_compatible */);
-
-        for (const auto &component : components) {
-            out << component << "/";
-        }
-
-        out << item.name()
-            << ".h>\n";
+        generateCppPackageInclude(out, item, item.name());
     }
 
     if (!mImportedNames.empty()) {
@@ -341,36 +349,16 @@
     out << "#ifndef " << guard << "\n";
     out << "#define " << guard << "\n\n";
 
-    std::vector<std::string> packageComponents;
-    getPackageAndVersionComponents(
-            &packageComponents, false /* cpp_compatible */);
+    generateCppPackageInclude(out, mPackage, ifaceName);
 
-    out << "#include <";
-    for (const auto &component : packageComponents) {
-        out << component << "/";
-    }
-    out << ifaceName << ".h>\n\n";
+    out << "\n";
 
     for (const auto &item : mImportedNames) {
         if (item.name() == "types") {
             continue;
         }
 
-        out << "#include <";
-
-        std::vector<std::string> components;
-        item.getPackageAndVersionComponents(
-                &components, false /* cpp_compatible */);
-
-        for (const auto &component : components) {
-            out << component << "/";
-        }
-
-        const std::string itemBaseName = item.getInterfaceBaseName();
-
-        out << "Bn"
-            << itemBaseName
-            << ".h>\n";
+        generateCppPackageInclude(out, item, "Bn" + item.getInterfaceBaseName());
     }
 
     out << "\n";
@@ -416,14 +404,10 @@
 }
 
 status_t AST::generateStubMethod(Formatter &out,
-                                 const std::string &className,
-                                 const Method *method,
-                                 bool specifyNamespaces) const {
+                                 const Method *method) const {
     out << "inline ";
 
-    method->generateCppSignature(out,
-                                 className,
-                                 specifyNamespaces);
+    method->generateCppSignature(out);
 
     const bool returnsValue = !method->results().empty();
     const TypedVar *elidedReturn = method->canElideCallback();
@@ -456,25 +440,9 @@
     return OK;
 }
 
-status_t AST::generateProxyDeclaration(Formatter &out,
-                                       const std::string &className,
-                                       const Method *method,
-                                       bool specifyNamespaces) const {
-
-    method->generateCppSignature(out,
-                                 className,
-                                 specifyNamespaces);
-    out << " override;\n";
-
-    return OK;
-}
-
-
 status_t AST::generatePassthroughMethod(Formatter &out,
-                                        const std::string &className,
-                                        const Method *method,
-                                        bool specifyNamespaces) const {
-    method->generateCppSignature(out, className, specifyNamespaces);
+                                        const Method *method) const {
+    method->generateCppSignature(out);
 
     out << " {\n";
     out.indent();
@@ -486,14 +454,21 @@
         generateCheckNonNull(out, "_hidl_cb");
     }
 
-    out << "return ";
+    generateCppInstrumentationCall(
+            out,
+            InstrumentationEvent::PASSTHROUGH_ENTRY,
+            method);
+
+    out << "auto _hidl_return = ";
 
     if (method->isOneway()) {
         out << "addOnewayTask([this";
         for (const auto &arg : method->args()) {
             out << ", " << arg->name();
         }
-        out << "] {this->";
+        out << "] {\n";
+        out.indent();
+        out << "this->";
     }
 
     out << "mImpl->"
@@ -515,12 +490,19 @@
 
         out << "_hidl_cb";
     }
-    out << ")";
+    out << ");\n\n";
+
+    generateCppInstrumentationCall(
+        out,
+        InstrumentationEvent::PASSTHROUGH_EXIT,
+        method);
 
     if (method->isOneway()) {
-        out << ";})";
+        out.unindent();
+        out << "});\n";
     }
-    out << ";\n";
+
+    out << "return _hidl_return;\n";
 
     out.unindent();
     out << "}\n";
@@ -528,11 +510,7 @@
     return OK;
 }
 
-status_t AST::generateMethods(
-        Formatter &out,
-        const std::string &className,
-        MethodLocation type,
-        bool specifyNamespaces) const {
+status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
 
     const Interface *iface = mRootScope->getInterface();
 
@@ -550,42 +528,7 @@
                 << " follow.\n";
             prevIterface = superInterface;
         }
-        status_t err;
-        switch(type) {
-            case STUB_HEADER:
-                err = generateStubMethod(out,
-                                         className,
-                                         method,
-                                         specifyNamespaces);
-                break;
-            case PROXY_HEADER:
-                err = generateProxyDeclaration(out,
-                                               className,
-                                               method,
-                                               specifyNamespaces);
-                break;
-            case IMPL_HEADER:
-                err = generateStubImplDeclaration(out,
-                                                  className,
-                                                  method,
-                                                  specifyNamespaces);
-                break;
-            case IMPL_SOURCE:
-                err = generateStubImplMethod(out,
-                                             className,
-                                             method,
-                                             specifyNamespaces);
-                break;
-            case PASSTHROUGH_HEADER:
-                err = generatePassthroughMethod(out,
-                                                className,
-                                                method,
-                                                specifyNamespaces);
-                break;
-            default:
-                LOG(ERROR) << "Unkown method type: " << type;
-                err = UNKNOWN_ERROR;
-        }
+        status_t err = gen(method, superInterface);
 
         if (err != OK) {
             return err;
@@ -628,15 +571,8 @@
     out << "#ifndef " << guard << "\n";
     out << "#define " << guard << "\n\n";
 
-    std::vector<std::string> packageComponents;
-    getPackageAndVersionComponents(
-            &packageComponents, false /* cpp_compatible */);
-
-    out << "#include <";
-    for (const auto &component : packageComponents) {
-        out << component << "/";
-    }
-    out << "IHw" << baseName << ".h>\n\n";
+    generateCppPackageInclude(out, mPackage, "IHw" + baseName);
+    out << "\n";
 
     enterLeaveNamespace(out, true /* enter */);
     out << "\n";
@@ -664,10 +600,9 @@
     out.unindent();
     out.unindent();
 
-    status_t err = generateMethods(out,
-                                   "" /* class name */,
-                                   MethodLocation::STUB_HEADER,
-                                   true /* specify namespaces */);
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        return generateStubMethod(out, method);
+    });
 
     if (err != OK) {
         return err;
@@ -719,11 +654,8 @@
     getPackageAndVersionComponents(
             &packageComponents, false /* cpp_compatible */);
 
-    out << "#include <";
-    for (const auto &component : packageComponents) {
-        out << component << "/";
-    }
-    out << "IHw" << baseName << ".h>\n\n";
+    generateCppPackageInclude(out, mPackage, "IHw" + baseName);
+    out << "\n";
 
     enterLeaveNamespace(out, true /* enter */);
     out << "\n";
@@ -744,10 +676,11 @@
 
     out << "virtual bool isRemote() const override { return true; }\n\n";
 
-    status_t err = generateMethods(out,
-                                   "" /* class name */,
-                                   MethodLocation::PROXY_HEADER,
-                                   true /* generate specify namespaces */);
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        method->generateCppSignature(out);
+        out << " override;\n";
+        return OK;
+    });
 
     if (err != OK) {
         return err;
@@ -800,33 +733,18 @@
 
     Formatter out(file);
 
-    std::vector<std::string> packageComponents;
-    getPackageAndVersionComponents(
-            &packageComponents, false /* cpp_compatible */);
-
-    std::string prefix;
-    for (const auto &component : packageComponents) {
-        prefix += component;
-        prefix += "/";
-    }
-
     if (isInterface) {
-        out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
-        out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
-        out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
+        generateCppPackageInclude(out, mPackage, "Bp" + baseName);
+        generateCppPackageInclude(out, mPackage, "Bn" + baseName);
+        generateCppPackageInclude(out, mPackage, "Bs" + baseName);
 
         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";
+            generateCppPackageInclude(out,
+                                      superType->fqName(),
+                                      "Bp" + superType->getBaseName());
         }
     } else {
-        out << "#include <" << prefix << "types.h>\n";
+        generateCppPackageInclude(out, mPackage, "types");
     }
 
     out << "\n";
@@ -868,7 +786,7 @@
         out << "IMPLEMENT_REGISTER_AND_GET_SERVICE("
             << baseName << ", "
             << "\"" << iface->fqName().package()
-            << iface->fqName().version() << "-impl.so\""
+            << iface->fqName().atVersion() << "-impl.so\""
             << ")\n";
     }
 
@@ -959,6 +877,178 @@
     }
 }
 
+status_t AST::generateProxyMethodSource(Formatter &out,
+                                        const std::string &klassName,
+                                        const Method *method,
+                                        const Interface *superInterface) const {
+
+    method->generateCppSignature(out,
+                                 klassName,
+                                 true /* specify namespaces */);
+
+    const bool returnsValue = !method->results().empty();
+    const TypedVar *elidedReturn = method->canElideCallback();
+
+    out << "{\n";
+
+    out.indent();
+
+    if (returnsValue && elidedReturn == nullptr) {
+        generateCheckNonNull(out, "_hidl_cb");
+    }
+
+    status_t status = generateCppInstrumentationCall(
+            out,
+            InstrumentationEvent::CLIENT_API_ENTRY,
+            method);
+    if (status != OK) {
+        return status;
+    }
+
+    out << "::android::hardware::Parcel _hidl_data;\n";
+    out << "::android::hardware::Parcel _hidl_reply;\n";
+    out << "::android::status_t _hidl_err;\n";
+    out << "::android::hardware::Status _hidl_status;\n\n";
+
+    declareCppReaderLocals(
+            out, method->results(), true /* forResults */);
+
+    out << "_hidl_err = _hidl_data.writeInterfaceToken(";
+    if (!method->isHidlReserved()) {
+        out << superInterface->fqName().cppNamespace()
+            << "::IHw"
+            << superInterface->getBaseName();
+    } else {
+        out << "::android::hardware::IHidlInterfaceBase";
+    }
+    out << "::descriptor);\n";
+
+    out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+    // First DFS: write all buffers and resolve pointers for parent
+    for (const auto &arg : method->args()) {
+        emitCppReaderWriter(
+                out,
+                "_hidl_data",
+                false /* parcelObjIsPointer */,
+                arg,
+                false /* reader */,
+                Type::ErrorMode_Goto,
+                false /* addPrefixToName */);
+    }
+
+    // Second DFS: resolve references.
+    for (const auto &arg : method->args()) {
+        emitCppResolveReferences(
+                out,
+                "_hidl_data",
+                false /* parcelObjIsPointer */,
+                arg,
+                false /* reader */,
+                Type::ErrorMode_Goto,
+                false /* addPrefixToName */);
+    }
+
+    out << "_hidl_err = remote()->transact("
+        << method->getSerialId()
+        << " /* "
+        << method->name()
+        << " */, _hidl_data, &_hidl_reply";
+
+    if (method->isOneway()) {
+        out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
+    }
+    out << ");\n";
+
+    out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+    if (!method->isOneway()) {
+        out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
+        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+        out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
+
+
+        // First DFS: write all buffers and resolve pointers for parent
+        for (const auto &arg : method->results()) {
+            emitCppReaderWriter(
+                    out,
+                    "_hidl_reply",
+                    false /* parcelObjIsPointer */,
+                    arg,
+                    true /* reader */,
+                    Type::ErrorMode_Goto,
+                    true /* addPrefixToName */);
+        }
+
+        // Second DFS: resolve references.
+        for (const auto &arg : method->results()) {
+            emitCppResolveReferences(
+                    out,
+                    "_hidl_reply",
+                    false /* parcelObjIsPointer */,
+                    arg,
+                    true /* reader */,
+                    Type::ErrorMode_Goto,
+                    true /* addPrefixToName */);
+        }
+
+        if (returnsValue && elidedReturn == nullptr) {
+            out << "_hidl_cb(";
+
+            bool first = true;
+            for (const auto &arg : method->results()) {
+                if (!first) {
+                    out << ", ";
+                }
+
+                if (arg->type().resultNeedsDeref()) {
+                    out << "*";
+                }
+                out << "_hidl_out_" << arg->name();
+
+                first = false;
+            }
+
+            out << ");\n\n";
+        }
+        status_t status = generateCppInstrumentationCall(
+                out,
+                InstrumentationEvent::CLIENT_API_EXIT,
+                method);
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    if (elidedReturn != nullptr) {
+        std::string extra;
+        out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+        out << "return ::android::hardware::Return<";
+        out << elidedReturn->type().getCppResultType(&extra)
+            << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
+    } else {
+        out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+        out << "return ::android::hardware::Return<void>();\n\n";
+    }
+
+    out.unindent();
+    out << "_hidl_error:\n";
+    out.indent();
+    out << "_hidl_status.setFromStatusT(_hidl_err);\n";
+    out << "return ::android::hardware::Return<";
+    if (elidedReturn != nullptr) {
+        std::string extra;
+        out << method->results().at(0)->type().getCppResultType(&extra);
+    } else {
+        out << "void";
+    }
+    out << ">(_hidl_status);\n";
+
+    out.unindent();
+    out << "}\n\n";
+    return OK;
+}
+
 status_t AST::generateProxySource(
         Formatter &out, const std::string &baseName) const {
     const std::string klassName = "Bp" + baseName;
@@ -985,181 +1075,11 @@
     out.unindent();
     out << "}\n\n";
 
-    const Interface *iface = mRootScope->getInterface();
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
+        return generateProxyMethodSource(out, klassName, method, superInterface);
+    });
 
-    for (const auto &tuple : iface->allMethodsFromRoot()) {
-        const Method *method = tuple.method();
-        const Interface *superInterface = tuple.interface();
-        method->generateCppSignature(out,
-                                     klassName,
-                                     true /* specify namespaces */);
-
-        const bool returnsValue = !method->results().empty();
-        const TypedVar *elidedReturn = method->canElideCallback();
-
-        out << "{\n";
-
-        out.indent();
-
-        if (returnsValue && elidedReturn == nullptr) {
-            generateCheckNonNull(out, "_hidl_cb");
-        }
-
-        status_t status = generateCppInstrumentationCall(
-                out,
-                InstrumentationEvent::CLIENT_API_ENTRY,
-                superInterface,
-                method);
-        if (status != OK) {
-            return status;
-        }
-
-        out << "::android::hardware::Parcel _hidl_data;\n";
-        out << "::android::hardware::Parcel _hidl_reply;\n";
-        out << "::android::status_t _hidl_err;\n";
-        out << "::android::hardware::Status _hidl_status;\n\n";
-
-        declareCppReaderLocals(
-                out, method->results(), true /* forResults */);
-
-        out << "_hidl_err = _hidl_data.writeInterfaceToken(";
-        if (!method->isHidlReserved()) {
-            out << superInterface->fqName().cppNamespace()
-                << "::IHw"
-                << superInterface->getBaseName();
-        } else {
-            out << "::android::hardware::IHidlInterfaceBase";
-        }
-        out << "::descriptor);\n";
-
-        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-        // First DFS: write all buffers and resolve pointers for parent
-        for (const auto &arg : method->args()) {
-            emitCppReaderWriter(
-                    out,
-                    "_hidl_data",
-                    false /* parcelObjIsPointer */,
-                    arg,
-                    false /* reader */,
-                    Type::ErrorMode_Goto,
-                    false /* addPrefixToName */);
-        }
-
-        // Second DFS: resolve references.
-        for (const auto &arg : method->args()) {
-            emitCppResolveReferences(
-                    out,
-                    "_hidl_data",
-                    false /* parcelObjIsPointer */,
-                    arg,
-                    false /* reader */,
-                    Type::ErrorMode_Goto,
-                    false /* addPrefixToName */);
-        }
-
-        out << "_hidl_err = remote()->transact("
-            << method->getSerialId()
-            << " /* "
-            << method->name()
-            << " */, _hidl_data, &_hidl_reply";
-
-        if (method->isOneway()) {
-            out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
-        }
-        out << ");\n";
-
-        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-        if (!method->isOneway()) {
-            out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
-            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-            out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
-
-
-            // First DFS: write all buffers and resolve pointers for parent
-            for (const auto &arg : method->results()) {
-                emitCppReaderWriter(
-                        out,
-                        "_hidl_reply",
-                        false /* parcelObjIsPointer */,
-                        arg,
-                        true /* reader */,
-                        Type::ErrorMode_Goto,
-                        true /* addPrefixToName */);
-            }
-
-            // Second DFS: resolve references.
-            for (const auto &arg : method->results()) {
-                emitCppResolveReferences(
-                        out,
-                        "_hidl_reply",
-                        false /* parcelObjIsPointer */,
-                        arg,
-                        true /* reader */,
-                        Type::ErrorMode_Goto,
-                        true /* addPrefixToName */);
-            }
-
-            if (returnsValue && elidedReturn == nullptr) {
-                out << "_hidl_cb(";
-
-                bool first = true;
-                for (const auto &arg : method->results()) {
-                    if (!first) {
-                        out << ", ";
-                    }
-
-                    if (arg->type().resultNeedsDeref()) {
-                        out << "*";
-                    }
-                    out << "_hidl_out_" << arg->name();
-
-                    first = false;
-                }
-
-                out << ");\n\n";
-            }
-            status_t status = generateCppInstrumentationCall(
-                    out,
-                    InstrumentationEvent::CLIENT_API_EXIT,
-                    superInterface,
-                    method);
-            if (status != OK) {
-                return status;
-            }
-        }
-
-        if (elidedReturn != nullptr) {
-            std::string extra;
-            out << "_hidl_status.setFromStatusT(_hidl_err);\n";
-            out << "return ::android::hardware::Return<";
-            out << elidedReturn->type().getCppResultType(&extra)
-                << ">(_hidl_out_" << elidedReturn->name() << ");\n\n";
-        } else {
-            out << "_hidl_status.setFromStatusT(_hidl_err);\n";
-            out << "return ::android::hardware::Return<void>();\n\n";
-        }
-
-        out.unindent();
-        out << "_hidl_error:\n";
-        out.indent();
-        out << "_hidl_status.setFromStatusT(_hidl_err);\n";
-        out << "return ::android::hardware::Return<";
-        if (elidedReturn != nullptr) {
-            std::string extra;
-            out << method->results().at(0)->type().getCppResultType(&extra);
-        } else {
-            out << "void";
-        }
-        out << ">(_hidl_status);\n";
-
-        out.unindent();
-        out << "}\n\n";
-    }
-
-
-    return OK;
+    return err;
 }
 
 status_t AST::generateStubSource(
@@ -1335,7 +1255,6 @@
     status_t status = generateCppInstrumentationCall(
             out,
             InstrumentationEvent::SERVER_API_ENTRY,
-            iface,
             method);
     if (status != OK) {
         return status;
@@ -1390,7 +1309,6 @@
         status_t status = generateCppInstrumentationCall(
                 out,
                 InstrumentationEvent::SERVER_API_EXIT,
-                iface,
                 method);
         if (status != OK) {
             return status;
@@ -1471,7 +1389,6 @@
             status_t status = generateCppInstrumentationCall(
                     out,
                     InstrumentationEvent::SERVER_API_EXIT,
-                    iface,
                     method);
             if (status != OK) {
                 return status;
@@ -1550,11 +1467,9 @@
             &packageComponents, false /* cpp_compatible */);
 
     out << "#include <future>\n";
-    out << "#include <";
-    for (const auto &component : packageComponents) {
-        out << component << "/";
-    }
-    out << ifaceName << ".h>\n\n";
+
+    generateCppPackageInclude(out, mPackage, ifaceName);
+    out << "\n";
 
     if (supportOneway) {
         out << "#include <hidl/TaskRunner.h>\n";
@@ -1566,7 +1481,7 @@
     out << "struct "
         << klassName
         << " : " << ifaceName
-        << " {\n";
+        << ", HidlInstrumentor {\n";
 
     out.indent();
     out << "explicit "
@@ -1575,10 +1490,9 @@
         << ifaceName
         << "> impl);\n";
 
-    status_t err = generateMethods(out,
-                                   "" /* class name */,
-                                   MethodLocation::PASSTHROUGH_HEADER,
-                                   true /* specify namespaces */);
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        return generatePassthroughMethod(out, method);
+    });
 
     if (err != OK) {
         return err;
@@ -1683,7 +1597,9 @@
         << klassName
         << "(const sp<"
         << iface->fullName()
-        << "> impl) : mImpl(impl) {";
+        << "> impl) : HidlInstrumentor(\""
+        << iface->fqName().string()
+        << "\"), mImpl(impl) {";
     if (iface->hasOnewayMethods()) {
         out << "\n";
         out.indentBlock([&] {
@@ -1722,7 +1638,7 @@
 status_t AST::generateCppInstrumentationCall(
         Formatter &out,
         InstrumentationEvent event,
-        const Interface *iface, const Method *method) const {
+        const Method *method) const {
     out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
     out.indent();
     out << "std::vector<void *> _hidl_args;\n";
@@ -1742,17 +1658,10 @@
         case SERVER_API_EXIT:
         {
             event_str = "InstrumentationEvent::SERVER_API_EXIT";
-            const TypedVar *elidedReturn = method->canElideCallback();
-            if (elidedReturn != nullptr) {
+            for (const auto &arg : method->results()) {
                 out << "_hidl_args.push_back((void *)&"
-                    << elidedReturn->name()
+                    << arg->name()
                     << ");\n";
-            } else {
-                for (const auto &arg : method->results()) {
-                    out << "_hidl_args.push_back((void *)&"
-                        << arg->name()
-                        << ");\n";
-                }
             }
             break;
         }
@@ -1778,16 +1687,31 @@
             }
             break;
         }
-        case SYNC_CALLBACK_ENTRY:
-        case SYNC_CALLBACK_EXIT:
-        case ASYNC_CALLBACK_ENTRY:
-        case ASYNC_CALLBACK_EXIT:
+        case PASSTHROUGH_ENTRY:
         {
-            LOG(ERROR) << "Not supported instrumentation event: " << event;
+            event_str = "InstrumentationEvent::PASSTHROUGH_ENTRY";
+            for (const auto &arg : method->args()) {
+                out << "_hidl_args.push_back((void *)&"
+                    << arg->name()
+                    << ");\n";
+            }
+            break;
+        }
+        case PASSTHROUGH_EXIT:
+        {
+            event_str = "InstrumentationEvent::PASSTHROUGH_EXIT";
+            // TODO(b/32576620): passthrough return values
+            break;
+        }
+        default:
+        {
+            LOG(ERROR) << "Unsupported instrumentation event: " << event;
             return UNKNOWN_ERROR;
         }
     }
 
+    const Interface *iface = mRootScope->getInterface();
+
     out << "for (auto callback: mInstrumentationCallbacks) {\n";
     out.indent();
     out << "callback("
@@ -1795,7 +1719,7 @@
         << ", \""
         << mPackage.package()
         << "\", \""
-        << mPackage.getPackageFullVersion()
+        << mPackage.version()
         << "\", \""
         << iface->localName()
         << "\", \""
diff --git a/generateCppImpl.cpp b/generateCppImpl.cpp
index 11ec1d6..25310f5 100644
--- a/generateCppImpl.cpp
+++ b/generateCppImpl.cpp
@@ -48,15 +48,14 @@
 
 status_t AST::generateStubImplMethod(Formatter &out,
                                      const std::string &className,
-                                     const Method *method,
-                                     bool specifyNamespaces) const {
+                                     const Method *method) const {
 
     // ignore HIDL reserved methods -- implemented in IFoo already.
     if (method->isHidlReserved()) {
         return OK;
     }
 
-    method->generateCppSignature(out, className, specifyNamespaces);
+    method->generateCppSignature(out, className, false /* specifyNamespaces */);
 
     out << " {\n";
 
@@ -81,24 +80,6 @@
     return OK;
 }
 
-status_t AST::generateStubImplDeclaration(Formatter &out,
-                                          const std::string &className,
-                                          const Method *method,
-                                          bool specifyNamespaces) const {
-
-    // ignore HIDL reserved methods -- implemented in IFoo already.
-    if (method->isHidlReserved()) {
-        return OK;
-    }
-
-    method->generateCppSignature(out,
-                                 className,
-                                 specifyNamespaces);
-    out << " override;\n";
-
-    return OK;
-}
-
 status_t AST::generateStubImplHeader(const std::string &outputPath) const {
     std::string ifaceName;
     if (!AST::isInterface(&ifaceName)) {
@@ -128,15 +109,7 @@
     out << "#ifndef " << guard << "\n";
     out << "#define " << guard << "\n\n";
 
-    std::vector<std::string> packageComponents;
-    getPackageAndVersionComponents(
-            &packageComponents, false /* cpp_compatible */);
-
-    out << "#include <";
-    for (const auto &component : packageComponents) {
-        out << component << "/";
-    }
-    out << "I" << baseName << ".h>\n";
+    generateCppPackageInclude(out, mPackage, "I" + baseName);
 
     out << "#include <hidl/Status.h>\n\n";
     out << "#include <hidl/MQDescriptor.h>\n";
@@ -192,10 +165,16 @@
 
     out.indent();
 
-    status_t err = generateMethods(out,
-                                   "", /* class name */
-                                   MethodLocation::IMPL_HEADER,
-                                   false /* specify namespaces */);
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        // ignore HIDL reserved methods -- implemented in IFoo already.
+        if (method->isHidlReserved()) {
+            return OK;
+        }
+        method->generateCppSignature(out, "" /* className */,
+                false /* specifyNamespaces */);
+        out << " override;\n";
+        return OK;
+    });
 
     if (err != OK) {
         return err;
@@ -250,11 +229,9 @@
     // this is namespace aware code and doesn't require post-processing
     out.setNamespace("");
 
-    generateMethods(out,
-                    baseName,
-                    MethodLocation::IMPL_SOURCE,
-                    false /* specify namespaces */);
-
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        return generateStubImplMethod(out, baseName, method);
+    });
 
     out << ifaceName
         << "* ";
diff --git a/generateVts.cpp b/generateVts.cpp
index 35eb0d0..d2e943f 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -102,7 +102,7 @@
     Formatter out(file);
 
     out << "component_class: HAL_HIDL\n";
-    out << "component_type_version: " << mPackage.getPackageFullVersion()
+    out << "component_type_version: " << mPackage.version()
         << "\n";
     out << "component_name: \""
         << (isInterface ? ifaceName : "types")
diff --git a/main.cpp b/main.cpp
index d95dadb..1524080 100644
--- a/main.cpp
+++ b/main.cpp
@@ -731,14 +731,14 @@
     out.unindent();
 
     out << "],\n";
-    out.unindent();
 
     out << "export_shared_lib_headers: [\n";
     out.indent();
     out << "\"libhidl\",\n"
         << "\"libhwbinder\",\n"
-        << "\"libutils\",\n"
-        << "],\n";
+        << "\"libutils\",\n";
+    out.unindent();
+    out << "],\n";
     out.unindent();
 
     out << "}\n";
diff --git a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
index e2a3e5b..e39ea7c 100644
--- a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
+++ b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
@@ -11,11 +11,11 @@
         name: "sendEvent"
         arg: {
             type: TYPE_ENUM
-            predefined_type: "NfcEvent"
+            predefined_type: "::android::hardware::nfc::V1_0::NfcEvent"
         }
         arg: {
             type: TYPE_ENUM
-            predefined_type: "NfcStatus"
+            predefined_type: "::android::hardware::nfc::V1_0::NfcStatus"
         }
     }
 
diff --git a/test/data/android/hardware/nfc/1.0/types.vts b/test/data/android/hardware/nfc/1.0/types.vts
index 8e4f93b..e43db1e 100644
--- a/test/data/android/hardware/nfc/1.0/types.vts
+++ b/test/data/android/hardware/nfc/1.0/types.vts
@@ -6,7 +6,7 @@
 
 
 attribute: {
-    name: "NfcEvent"
+    name: "::android::hardware::nfc::V1_0::NfcEvent"
     type: TYPE_ENUM
     enum_value: {
         scalar_type: "uint32_t"
@@ -43,7 +43,7 @@
 }
 
 attribute: {
-    name: "NfcStatus"
+    name: "::android::hardware::nfc::V1_0::NfcStatus"
     type: TYPE_ENUM
     enum_value: {
         scalar_type: "uint32_t"
diff --git a/test/main.cpp b/test/main.cpp
index 50bada6..8943a9e 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -444,10 +444,11 @@
     Abc abcParam{};
     abcParam.x = "alphabet";
     abcParam.y = 3.14f;
-    abcParam.z = new native_handle_t();
+    native_handle_t *handle = native_handle_create(0, 0);
+    abcParam.z = handle;
     EXPECT_OK(foo->haveATypeFromAnotherFile(abcParam));
     ALOGI("CLIENT haveATypeFromAnotherFile returned.");
-    delete abcParam.z;
+    native_handle_delete(handle);
     abcParam.z = NULL;
 }
 
@@ -637,10 +638,21 @@
     if (gMode == BINDERIZED) {
         Abc xyz;
         xyz.z = nullptr;
-        EXPECT_FAIL(foo->haveATypeFromAnotherFile(xyz));
+        EXPECT_FAIL(bar->expectNullHandle(nullptr, xyz, [](bool hIsNull, bool xyzHasNull) {
+            EXPECT_TRUE(hIsNull);
+            EXPECT_TRUE(xyzHasNull);
+        }));
     }
 }
 
+TEST_F(HidlTest, FooNullCallbackTest) {
+    EXPECT_OK(foo->echoNullInterface(nullptr,
+                [](const auto receivedNull, const auto &intf) {
+                   EXPECT_TRUE(receivedNull);
+                   EXPECT_EQ(intf, nullptr);
+                }));
+}
+
 TEST_F(HidlTest, FooNonNullCallbackTest) {
     hidl_array<hidl_string, 5, 3> in;