Merge "ABI stable smaller HIDL libs"
diff --git a/AST.h b/AST.h
index c328434..1fe514f 100644
--- a/AST.h
+++ b/AST.h
@@ -186,12 +186,15 @@
     void generateTemplatizationLink(Formatter& out) const;
     void generateCppTag(Formatter& out, const std::string& tag) const;
 
-    status_t generateMethods(Formatter &out, MethodGenerator gen) const;
+    status_t generateMethods(Formatter &out, MethodGenerator gen, bool includeParents = true) const;
     status_t generateStubImplMethod(Formatter &out,
                                     const std::string &className,
                                     const Method *method) const;
     status_t generatePassthroughMethod(Formatter &out,
                                        const Method *method) const;
+    status_t generateStaticProxyMethodSource(Formatter &out,
+                                             const std::string &className,
+                                             const Method *method) const;
     status_t generateProxyMethodSource(Formatter &out,
                                        const std::string &className,
                                        const Method *method,
@@ -205,8 +208,12 @@
     status_t generateStubSource(
             Formatter &out, const Interface *iface) const;
 
-    status_t generateStubSourceForMethod(
-            Formatter &out, const Interface *iface, const Method *method) const;
+    status_t generateStubSourceForMethod(Formatter &out,
+                                         const Method *method,
+                                         const Interface *superInterface) const;
+    status_t generateStaticStubMethodSource(Formatter &out,
+                                            const std::string &className,
+                                            const Method *method) const;
 
     status_t generatePassthroughSource(Formatter &out) const;
 
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 22bc893..368f520 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -784,7 +784,7 @@
     return OK;
 }
 
-status_t AST::generateMethods(Formatter &out, MethodGenerator gen) const {
+status_t AST::generateMethods(Formatter &out, MethodGenerator gen, bool includeParent) const {
     const Interface* iface = mRootScope.getInterface();
 
     const Interface *prevIterface = nullptr;
@@ -792,6 +792,10 @@
         const Method *method = tuple.method();
         const Interface *superInterface = tuple.interface();
 
+        if (!includeParent && superInterface != iface) {
+            continue;
+        }
+
         if(prevIterface != superInterface) {
             if (prevIterface != nullptr) {
                 out << "\n";
@@ -896,11 +900,34 @@
     generateCppTag(out, "android::hardware::details::bnhw_tag");
 
     out << "::android::sp<" << iface->localName() << "> getImpl() { return _hidl_mImpl; };\n";
+
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
+            return OK;
+        }
+
+        out << "static ::android::status_t _hidl_" << method->name() << "(\n";
+
+        out.indent(2, [&] {
+            out << "::android::hidl::base::V1_0::BnHwBase* _hidl_this,\n"
+                << "const ::android::hardware::Parcel &_hidl_data,\n"
+                << "::android::hardware::Parcel *_hidl_reply,\n"
+                << "TransactCallback _hidl_cb);\n";
+        }).endl().endl();
+
+        return OK;
+    }, false /* include parents */);
+
+    if (err != OK) {
+        return err;
+    }
+
     out.unindent();
     out << "private:\n";
     out.indent();
 
-    status_t err = generateMethods(out, [&](const Method *method, const Interface *iface) {
+
+    err = generateMethods(out, [&](const Method *method, const Interface *iface) {
         if (!method->isHidlReserved() || !method->overridesCppImpl(IMPL_STUB_IMPL)) {
             return OK;
         }
@@ -991,6 +1018,31 @@
     out << "virtual bool isRemote() const override { return true; }\n\n";
 
     status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
+            return OK;
+        }
+
+        out << "static ";
+        method->generateCppReturnType(out);
+        out << " _hidl_"
+            << method->name()
+            << "("
+            << "::android::hardware::IInterface* _hidl_this, "
+            << "::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor";
+
+        if (!method->hasEmptyCppArgSignature()) {
+            out << ", ";
+        }
+        method->emitCppArgSignature(out);
+        out << ");\n";
+        return OK;
+    }, false /* include parents */);
+
+    if (err != OK) {
+        return err;
+    }
+
+    err = generateMethods(out, [&](const Method *method, const Interface *) {
         method->generateCppSignature(out);
         out << " override;\n";
         return OK;
@@ -1245,25 +1297,90 @@
                                         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 (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
-        method->cppImpl(IMPL_PROXY, out);
-        out.unindent();
-        out << "}\n\n";
+        out.block([&] {
+            method->cppImpl(IMPL_PROXY, out);
+        }).endl().endl();
         return OK;
     }
 
+    status_t err = OK;
+
+    out.block([&] {
+        const bool returnsValue = !method->results().empty();
+        const TypedVar *elidedReturn = method->canElideCallback();
+
+        method->generateCppReturnType(out);
+
+        out << " _hidl_out = "
+            << superInterface->fqName().cppNamespace()
+            << "::"
+            << superInterface->getProxyName()
+            << "::_hidl_"
+            << method->name()
+            << "(this, this";
+
+        if (!method->hasEmptyCppArgSignature()) {
+            out << ", ";
+        }
+
+        out.join(method->args().begin(), method->args().end(), ", ", [&](const auto &arg) {
+            out << arg->name();
+        });
+
+        if (returnsValue && elidedReturn == nullptr) {
+            if (!method->args().empty()) {
+                out << ", ";
+            }
+            out << "_hidl_cb";
+        }
+
+        out << ");\n\n";
+
+        out << "return _hidl_out;\n";
+    }).endl().endl();
+
+    return err;
+}
+
+status_t AST::generateStaticProxyMethodSource(Formatter &out,
+                                              const std::string &klassName,
+                                              const Method *method) const {
+    if (method->isHidlReserved() && method->overridesCppImpl(IMPL_PROXY)) {
+        return OK;
+    }
+
+    method->generateCppReturnType(out);
+
+    out << klassName
+        << "::_hidl_"
+        << method->name()
+        << "("
+        << "::android::hardware::IInterface *_hidl_this, "
+        << "::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor";
+
+    if (!method->hasEmptyCppArgSignature()) {
+        out << ", ";
+    }
+
+    method->emitCppArgSignature(out);
+    out << ") {\n";
+
+    out.indent();
+
+    out << "#ifdef __ANDROID_DEBUGGABLE__\n";
+    out << "bool mEnableInstrumentation = _hidl_this_instrumentor->isInstrumentationEnabled();\n";
+    out << "const auto &mInstrumentationCallbacks = _hidl_this_instrumentor->getInstrumentationCallbacks();\n";
+    out << "#else\n";
+    out << "(void) _hidl_this_instrumentor;\n";
+    out << "#endif // __ANDROID_DEBUGGABLE__\n";
+
+    const bool returnsValue = !method->results().empty();
+    const TypedVar *elidedReturn = method->canElideCallback();
     if (returnsValue && elidedReturn == nullptr) {
         generateCheckNonNull(out, "_hidl_cb");
     }
@@ -1282,7 +1399,7 @@
             out, method->results(), true /* forResults */);
 
     out << "_hidl_err = _hidl_data.writeInterfaceToken(";
-    out << superInterface->fqName().cppName();
+    out << klassName;
     out << "::descriptor);\n";
     out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
 
@@ -1318,7 +1435,7 @@
         // Start binder threadpool to handle incoming transactions
         out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
     }
-    out << "_hidl_err = remote()->transact("
+    out << "_hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact("
         << method->getSerialId()
         << " /* "
         << method->name()
@@ -1374,6 +1491,7 @@
             out << ");\n\n";
         }
     }
+
     generateCppInstrumentationCall(
             out,
             InstrumentationEvent::CLIENT_API_EXIT,
@@ -1432,7 +1550,15 @@
     out.unindent();
     out << "}\n\n";
 
-    status_t err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
+    status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        return generateStaticProxyMethodSource(out, klassName, method);
+    }, false /* include parents */);
+
+    if (err != OK) {
+        return err;
+    }
+
+    err = generateMethods(out, [&](const Method *method, const Interface *superInterface) {
         return generateProxyMethodSource(out, klassName, method, superInterface);
     });
 
@@ -1507,6 +1633,10 @@
     }).endl().endl();
 
     status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
+        return generateStaticStubMethodSource(out, klassName, method);
+    }, false /* include parents */);
+
+    err = generateMethods(out, [&](const Method *method, const Interface *) {
         if (!method->isHidlReserved() || !method->overridesCppImpl(IMPL_STUB_IMPL)) {
             return OK;
         }
@@ -1541,6 +1671,7 @@
     for (const auto &tuple : iface->allMethodsFromRoot()) {
         const Method *method = tuple.method();
         const Interface *superInterface = tuple.interface();
+
         out << "case "
             << method->getSerialId()
             << " /* "
@@ -1549,8 +1680,7 @@
 
         out.indent();
 
-        status_t err =
-            generateStubSourceForMethod(out, superInterface, method);
+        status_t err = generateStubSourceForMethod(out, method, superInterface);
 
         if (err != OK) {
             return err;
@@ -1604,20 +1734,61 @@
 }
 
 status_t AST::generateStubSourceForMethod(
-        Formatter &out, const Interface *iface, const Method *method) const {
+        Formatter &out,
+        const Method *method,
+        const Interface* superInterface) const {
+
     if (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB)) {
         method->cppImpl(IMPL_STUB, out);
         out << "break;\n";
         return OK;
     }
 
+    out << "_hidl_err = "
+        << superInterface->fqName().cppNamespace()
+        << "::"
+        << superInterface->getStubName()
+        << "::_hidl_"
+        << method->name()
+        << "(this, _hidl_data, _hidl_reply, _hidl_cb);\n";
+    out << "break;\n";
+
+    return OK;
+}
+
+status_t AST::generateStaticStubMethodSource(Formatter &out,
+                                             const std::string &klassName,
+                                             const Method *method) const {
+    if (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB)) {
+        return OK;
+    }
+
+    out << "::android::status_t " << klassName << "::_hidl_" << method->name() << "(\n";
+
+    out.indent();
+    out.indent();
+
+    out << "::android::hidl::base::V1_0::BnHwBase* _hidl_this,\n"
+        << "const ::android::hardware::Parcel &_hidl_data,\n"
+        << "::android::hardware::Parcel *_hidl_reply,\n"
+        << "TransactCallback _hidl_cb) {\n";
+
+    out.unindent();
+
+    out << "#ifdef __ANDROID_DEBUGGABLE__\n";
+    out << "bool mEnableInstrumentation = _hidl_this->isInstrumentationEnabled();\n";
+    out << "const auto &mInstrumentationCallbacks = _hidl_this->getInstrumentationCallbacks();\n";
+    out << "#endif // __ANDROID_DEBUGGABLE__\n\n";
+
+    out << "::android::status_t _hidl_err = ::android::OK;\n";
+
     out << "if (!_hidl_data.enforceInterface("
-        << iface->fullName()
-        << "::descriptor)) {\n";
+        << klassName
+        << "::Pure::descriptor)) {\n";
 
     out.indent();
     out << "_hidl_err = ::android::BAD_TYPE;\n";
-    out << "break;\n";
+    out << "return _hidl_err;\n";
     out.unindent();
     out << "}\n\n";
 
@@ -1631,7 +1802,7 @@
                 false /* parcelObjIsPointer */,
                 arg,
                 true /* reader */,
-                Type::ErrorMode_Break,
+                Type::ErrorMode_Return,
                 false /* addPrefixToName */);
     }
 
@@ -1643,7 +1814,7 @@
                 false /* parcelObjIsPointer */,
                 arg,
                 true /* reader */,
-                Type::ErrorMode_Break,
+                Type::ErrorMode_Return,
                 false /* addPrefixToName */);
     }
 
@@ -1654,9 +1825,7 @@
 
     const bool returnsValue = !method->results().empty();
     const TypedVar *elidedReturn = method->canElideCallback();
-    const std::string callee =
-            (method->isHidlReserved() && method->overridesCppImpl(IMPL_STUB_IMPL))
-            ? "this" : "_hidl_mImpl";
+    const std::string callee = "static_cast<" + klassName + "*>(_hidl_this)->_hidl_mImpl";
 
     if (elidedReturn != nullptr) {
         out << elidedReturn->type().getCppResultType()
@@ -1775,6 +1944,7 @@
             out << "});\n\n";
         } else {
             out << ");\n\n";
+            out << "(void) _hidl_cb;\n\n";
             generateCppInstrumentationCall(
                     out,
                     InstrumentationEvent::SERVER_API_EXIT,
@@ -1796,7 +1966,9 @@
         }
     }
 
-    out << "break;\n";
+    out << "return _hidl_err;\n";
+    out.unindent();
+    out << "}\n\n";
 
     return OK;
 }