Add instrumentation code on proxy side.

* Only works for C++ backend for now.

Bug: 31266145
Test: make hidl_test
Change-Id: I18a78b274448fee12a8d340a891ba0c4f7a3a738
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 1325028..680a7b8 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -666,12 +666,13 @@
         return err;
     }
 
-    // Generated code for instrumentation.
-    out << "// for hidl instrumentation.\n";
-    out << "std::vector<InstrumentationCallback> instrumentationCallbacks;\n\n";
-    out << "bool enableInstrumentation = false;\n";
 
     out.unindent();
+    out << "private:\n";
+
+    out.indent();
+    emitCppInstrumentationDecl(out);
+    out.unindent();
 
     out << "};\n\n";
 
@@ -752,6 +753,12 @@
     }
 
     out.unindent();
+    out << "private:\n";
+
+    out.indent();
+    emitCppInstrumentationDecl(out);
+
+    out.unindent();
 
     out << "};\n\n";
 
@@ -950,6 +957,8 @@
         << baseName
         << ">(_hidl_impl) {\n";
 
+    emitCppInstrumentationInit(out, baseName);
+
     out.unindent();
     out.unindent();
     out << "}\n\n";
@@ -981,6 +990,15 @@
                 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";
@@ -1084,6 +1102,14 @@
 
                     out << ");\n\n";
                 }
+                status_t status = generateCppInstrumentationCall(
+                        out,
+                        InstrumentationEvent::CLIENT_API_EXIT,
+                        superInterface,
+                        method);
+                if (status != OK) {
+                    return status;
+                }
             }
 
             if (elidedReturn != nullptr) {
@@ -1145,13 +1171,7 @@
         << baseName
         << ">(_hidl_impl) {\n";
 
-    out << "enableInstrumentation = "
-           "property_get_bool(\"hal.instrumentation.enable\", false);\n";
-    out << "registerInstrumentationCallbacks(\""
-        << mPackage.string()
-        << "::I"
-        << baseName
-        << "\", &instrumentationCallbacks);\n";
+    emitCppInstrumentationInit(out, baseName);
     out.unindent();
     out.unindent();
     out << "}\n\n";
@@ -1294,27 +1314,15 @@
                 false /* addPrefixToName */);
     }
 
-    out << "if (UNLIKELY(enableInstrumentation)) {\n";
-    out.indent();
-    out << "std::vector<void *> args;\n";
-    for (const auto &arg : method->args()) {
-        out << "args.push_back((void *)"
-            << (arg->type().resultNeedsDeref() ? "" : "&")
-            << arg->name()
-            << ");\n";
+    status_t status = generateCppInstrumentationCall(
+            out,
+            InstrumentationEvent::SERVER_API_ENTRY,
+            iface,
+            method);
+    if (status != OK) {
+        return status;
     }
 
-    out << "for (auto callback: instrumentationCallbacks) {\n";
-    out.indent();
-    out << "callback(InstrumentationEvent::SERVER_API_ENTRY, \""
-        << mPackage.package()
-        << "\", \"" << mPackage.version().substr(1) << "\", \""
-        << iface->localName() << "\", \"" << method->name() << "\", &args);\n";
-    out.unindent();
-    out << "}\n";
-    out.unindent();
-    out << "}\n\n";
-
     const bool returnsValue = !method->results().empty();
     const TypedVar *elidedReturn = method->canElideCallback();
 
@@ -1361,22 +1369,14 @@
                 Type::ErrorMode_Ignore,
                 false /* addPrefixToName */);
 
-        out << "if (UNLIKELY(enableInstrumentation)) {\n";
-        out.indent();
-        out << "std::vector<void *> results;\n";
-        out << "results.push_back((void *)&" << elidedReturn->name() << ");\n";
-
-        out << "for (auto callback: instrumentationCallbacks) {\n";
-        out.indent();
-        out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
-            << mPackage.package()
-            << "\", \"" << mPackage.version().substr(1) << "\", \""
-            << iface->localName() << "\", \"" << method->name()
-            << "\", &results);\n";
-        out.unindent();
-        out << "}\n";
-        out.unindent();
-        out << "}\n\n";
+        status_t status = generateCppInstrumentationCall(
+                out,
+                InstrumentationEvent::SERVER_API_EXIT,
+                iface,
+                method);
+        if (status != OK) {
+            return status;
+        }
 
         out << "_hidl_cb(*_hidl_reply);\n";
     } else {
@@ -1450,25 +1450,15 @@
                         false /* addPrefixToName */);
             }
 
-            out << "if (UNLIKELY(enableInstrumentation)) {\n";
-            out.indent();
-            out << "std::vector<void *> results;\n";
-            for (const auto &arg : method->results()) {
-                out << "results.push_back((void *)&" << arg->name() << ");\n";
+            status_t status = generateCppInstrumentationCall(
+                    out,
+                    InstrumentationEvent::SERVER_API_EXIT,
+                    iface,
+                    method);
+            if (status != OK) {
+                return status;
             }
 
-            out << "for (auto callback: instrumentationCallbacks) {\n";
-            out.indent();
-            out << "callback(InstrumentationEvent::SERVER_API_EXIT, \""
-                << mPackage.package()
-                << "\", \"" << mPackage.version().substr(1) << "\", \""
-                << iface->localName() << "\", \"" << method->name()
-                << "\", &results);\n";
-            out.unindent();
-            out << "}\n";
-            out.unindent();
-            out << "}\n\n";
-
             out << "_hidl_cb(*_hidl_reply);\n";
 
             out.unindent();
@@ -1659,5 +1649,108 @@
     return OK;
 }
 
+status_t AST::generateCppInstrumentationCall(
+        Formatter &out,
+        InstrumentationEvent event,
+        const Interface *iface, const Method *method) const {
+    out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
+    out.indent();
+    out << "std::vector<void *> args;\n";
+    std::string event_str = "";
+    switch (event) {
+        case SERVER_API_ENTRY:
+        {
+            event_str = "InstrumentationEvent::SERVER_API_ENTRY";
+            for (const auto &arg : method->args()) {
+                out << "args.push_back((void *)"
+                    << (arg->type().resultNeedsDeref() ? "" : "&")
+                    << arg->name()
+                    << ");\n";
+            }
+            break;
+        }
+        case SERVER_API_EXIT:
+        {
+            event_str = "InstrumentationEvent::SERVER_API_EXIT";
+            const TypedVar *elidedReturn = method->canElideCallback();
+            if (elidedReturn != nullptr) {
+                out << "args.push_back((void *)&" << elidedReturn->name()
+                    << ");\n";
+            } else {
+                for (const auto &arg : method->results()) {
+                    out << "args.push_back((void *)&" << arg->name()
+                        << ");\n";
+                }
+            }
+            break;
+        }
+        case CLIENT_API_ENTRY:
+        {
+            event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
+            for (const auto &arg : method->args()) {
+                out << "args.push_back((void *)&" << arg->name() << ");\n";
+            }
+            break;
+        }
+        case CLIENT_API_EXIT:
+        {
+            event_str = "InstrumentationEvent::CLIENT_API_EXIT";
+            for (const auto &arg : method->results()) {
+                out << "args.push_back((void *)"
+                    << (arg->type().resultNeedsDeref() ? "" : "&")
+                    << "_hidl_out_" << arg->name()
+                    << ");\n";
+            }
+            break;
+        }
+        case SYNC_CALLBACK_ENTRY:
+        case SYNC_CALLBACK_EXIT:
+        case ASYNC_CALLBACK_ENTRY:
+        case ASYNC_CALLBACK_EXIT:
+        {
+            LOG(ERROR) << "Not supported instrumentation event: " << event;
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    out << "for (auto callback: mInstrumentationCallbacks) {\n";
+    out.indent();
+    out << "callback("
+        << event_str
+        << ", \""
+        << mPackage.package()
+        << "\", \""
+        << mPackage.getPackageFullVersion()
+        << "\", \""
+        << iface->localName()
+        << "\", \""
+        << method->name()
+        << "\", &args);\n";
+    out.unindent();
+    out << "}\n";
+    out.unindent();
+    out << "}\n\n";
+
+    return OK;
+}
+
+void AST::emitCppInstrumentationDecl(
+        Formatter &out) const {
+    out << "// for hidl instrumentation.\n";
+    out << "std::vector<InstrumentationCallback> mInstrumentationCallbacks;\n";
+    out << "bool mEnableInstrumentation;\n";
+}
+
+void AST::emitCppInstrumentationInit(
+        Formatter &out, const std::string &baseName) const {
+    out << "mEnableInstrumentation = "
+        "property_get_bool(\"hal.instrumentation.enable\", false);\n";
+    out << "registerInstrumentationCallbacks(\""
+        << mPackage.string()
+        << "::I"
+        << baseName
+        << "\", &mInstrumentationCallbacks);\n";
+}
+
 }  // namespace android