BpHw* transact uses callback.

For Java passthrough case and for non-binder protocols.

Bug: 129150021
Test: ./test/run_all_device_tests.sh
Test: libhwbinder_benchmark (within variance)
Change-Id: I8830796bc48d822e494b197422e4ab0f26f45524
diff --git a/Type.cpp b/Type.cpp
index f953e71..1ac668e 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -525,7 +525,7 @@
     CHECK(!"Should not be here") << typeName();
 }
 
-void Type::handleError(Formatter &out, ErrorMode mode) const {
+void Type::handleError(Formatter &out, ErrorMode mode) {
     switch (mode) {
         case ErrorMode_Ignore:
         {
@@ -550,6 +550,16 @@
             out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n";
             break;
         }
+
+        case ErrorMode_ReturnNothing:
+        {
+            out << "if (_hidl_err != ::android::OK) { return; }\n\n";
+            break;
+        }
+        default:
+        {
+            LOG(FATAL) << "Should not be here";
+        }
     }
 }
 
diff --git a/Type.h b/Type.h
index 2462f56..e4a56db 100644
--- a/Type.h
+++ b/Type.h
@@ -195,6 +195,7 @@
         ErrorMode_Goto,
         ErrorMode_Break,
         ErrorMode_Return,
+        ErrorMode_ReturnNothing,
     };
     virtual void emitReaderWriter(
             Formatter &out,
@@ -341,9 +342,8 @@
 
     virtual bool isNeverStrongReference() const;
 
+    static void handleError(Formatter &out, ErrorMode mode);
    protected:
-    void handleError(Formatter &out, ErrorMode mode) const;
-
     void emitReaderWriterEmbeddedForTypeName(
             Formatter &out,
             const std::string &name,
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 06110ca..2b70cac 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -1097,7 +1097,9 @@
 
     const bool returnsValue = !method->results().empty();
     const NamedReference<Type>* elidedReturn = method->canElideCallback();
-    if (returnsValue && elidedReturn == nullptr) {
+    const bool hasCallback = returnsValue && elidedReturn == nullptr;
+
+    if (hasCallback) {
         generateCheckNonNull(out, "_hidl_cb");
     }
 
@@ -1110,10 +1112,13 @@
     out << "::android::hardware::Parcel _hidl_data;\n";
     out << "::android::hardware::Parcel _hidl_reply;\n";
     out << "::android::status_t _hidl_err;\n";
+    out << "::android::status_t _hidl_transact_err;\n";
     out << "::android::hardware::Status _hidl_status;\n\n";
 
-    declareCppReaderLocals(
-            out, method->results(), true /* forResults */);
+    if (!hasCallback) {
+        declareCppReaderLocals(
+                out, method->results(), true /* forResults */);
+    }
 
     out << "_hidl_err = _hidl_data.writeInterfaceToken(";
     out << klassName;
@@ -1152,7 +1157,7 @@
         // Start binder threadpool to handle incoming transactions
         out << "::android::hardware::ProcessState::self()->startThreadPool();\n";
     }
-    out << "_hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact("
+    out << "_hidl_transact_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact("
         << method->getSerialId()
         << " /* "
         << method->name()
@@ -1160,16 +1165,36 @@
 
     if (method->isOneway()) {
         out << ", " << Interface::FLAG_ONE_WAY->cppValue();
+    } else {
+        out << ", 0";
     }
-    out << ");\n";
 
-    out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+    if (hasCallback) {
+        out << ", [&] (::android::hardware::Parcel& _hidl_reply) {\n";
+        out.indent();
+        declareCppReaderLocals(
+                out, method->results(), true /* forResults */);
+        out.endl();
+    } else {
+        out << ");\n";
+        out << "if (_hidl_transact_err != ::android::OK) \n";
+        out.block([&] {
+            out << "_hidl_err = _hidl_transact_err;\n";
+            out << "goto _hidl_error;\n";
+        }).endl().endl();
+    }
 
     if (!method->isOneway()) {
-        out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
-        out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-        out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
+        Type::ErrorMode errorMode = hasCallback ? Type::ErrorMode_ReturnNothing : Type::ErrorMode_Goto;
 
+        out << "_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);\n";
+        Type::handleError(out, errorMode);
+
+        if (hasCallback) {
+            out << "if (!_hidl_status.isOk()) { return; }\n\n";
+        } else {
+            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()) {
@@ -1179,7 +1204,7 @@
                     false /* parcelObjIsPointer */,
                     arg,
                     true /* reader */,
-                    Type::ErrorMode_Goto,
+                    errorMode,
                     true /* addPrefixToName */);
         }
 
@@ -1191,7 +1216,7 @@
                     false /* parcelObjIsPointer */,
                     arg,
                     true /* reader */,
-                    Type::ErrorMode_Goto,
+                    errorMode,
                     true /* addPrefixToName */);
         }
 
@@ -1215,6 +1240,17 @@
             method,
             superInterface);
 
+    if (hasCallback) {
+        out.unindent();
+        out << "});\n";
+        out << "if (_hidl_transact_err != ::android::OK) ";
+        out.block([&] {
+            out << "_hidl_err = _hidl_transact_err;\n";
+            out << "goto _hidl_error;\n";
+        }).endl().endl();
+        out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n";
+    }
+
     if (elidedReturn != nullptr) {
         out << "_hidl_status.setFromStatusT(_hidl_err);\n";
         out << "return ::android::hardware::Return<";