Merge "Add instrumentation code on proxy side."
diff --git a/AST.h b/AST.h
index 33c41e1..5195532 100644
--- a/AST.h
+++ b/AST.h
@@ -204,6 +204,30 @@
 
     status_t generatePassthroughSource(Formatter &out) const;
 
+
+    enum InstrumentationEvent {
+        SERVER_API_ENTRY = 0,
+        SERVER_API_EXIT,
+        CLIENT_API_ENTRY,
+        CLIENT_API_EXIT,
+        SYNC_CALLBACK_ENTRY,
+        SYNC_CALLBACK_EXIT,
+        ASYNC_CALLBACK_ENTRY,
+        ASYNC_CALLBACK_EXIT,
+    };
+
+    status_t generateCppInstrumentationCall(
+            Formatter &out,
+            InstrumentationEvent event,
+            const Interface *iface,
+            const Method *method) const;
+
+    void emitCppInstrumentationDecl(Formatter &out) const;
+
+    void emitCppInstrumentationInit(
+            Formatter &out,
+            const std::string &baseName) const;
+
     void declareCppReaderLocals(
             Formatter &out,
             const std::vector<TypedVar *> &arg,
diff --git a/FQName.cpp b/FQName.cpp
index 8bd3cdc..9bc271b 100644
--- a/FQName.cpp
+++ b/FQName.cpp
@@ -347,6 +347,12 @@
     return packageVersion.substr(dotPos + 1);
 }
 
+std::string FQName::getPackageFullVersion() const {
+    const std::string packageVersion = version();
+    CHECK_GT(packageVersion.length(), 1u);
+    return packageVersion.substr(1);
+}
+
 bool FQName::endsWith(const FQName &other) const {
     std::string s1 = string();
     std::string s2 = other.string();
diff --git a/FQName.h b/FQName.h
index b3e0002..e2d0159 100644
--- a/FQName.h
+++ b/FQName.h
@@ -142,6 +142,9 @@
 
     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;
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
 
diff --git a/generateVts.cpp b/generateVts.cpp
index c830918..2eba598 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -102,7 +102,8 @@
     Formatter out(file);
 
     out << "component_class: HAL_HIDL\n";
-    out << "component_type_version: " << mPackage.version().substr(1) << "\n";
+    out << "component_type_version: " << mPackage.getPackageFullVersion()
+        << "\n";
     out << "component_name: \""
         << (isInterface ? ifaceName : "types")
         << "\"\n\n";
diff --git a/test/data/android/hardware/tests/expression/1.0/BnExpression.h b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
index c0320fa..0fcecb1 100644
--- a/test/data/android/hardware/tests/expression/1.0/BnExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
@@ -10,21 +10,30 @@
 namespace V1_0 {
 
 struct BnExpression : public ::android::hardware::BnInterface<IExpression, IHwExpression> {
-  explicit BnExpression(const ::android::sp<IExpression> &_hidl_impl);
+    explicit BnExpression(const ::android::sp<IExpression> &_hidl_impl);
 
-  ::android::status_t onTransact(
-      uint32_t _hidl_code,
-      const ::android::hardware::Parcel &_hidl_data,
-      ::android::hardware::Parcel *_hidl_reply,
-      uint32_t _hidl_flags = 0,
-      TransactCallback _hidl_cb = nullptr) override;
+    ::android::status_t onTransact(
+            uint32_t _hidl_code,
+            const ::android::hardware::Parcel &_hidl_data,
+            ::android::hardware::Parcel *_hidl_reply,
+            uint32_t _hidl_flags = 0,
+            TransactCallback _hidl_cb = nullptr) override;
 
-  // Methods from IExpression follow.
+    // Methods from IExpression follow.
+    inline ::android::hardware::Return<void> foo1(const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>& array)  {
+        return mImpl->foo1(array);
+    };
+    inline ::android::hardware::Return<void> foo2(const hidl_array<int32_t, 13 /* (5 + 8) */>& array)  {
+        return mImpl->foo2(array);
+    };
+    inline ::android::hardware::Return<void> foo3(const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>& array)  {
+        return mImpl->foo3(array);
+    };
 
-  // for hidl instrumentation.
-  std::vector<InstrumentationCallback> instrumentationCallbacks;
-
-  bool enableInstrumentation = false;
+private:
+    // for hidl instrumentation.
+    std::vector<InstrumentationCallback> mInstrumentationCallbacks;
+    bool mEnableInstrumentation;
 };
 
 }  // namespace V1_0
diff --git a/test/data/android/hardware/tests/expression/1.0/BpExpression.h b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
index 7e2dcbf..33e4b91 100644
--- a/test/data/android/hardware/tests/expression/1.0/BpExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
@@ -10,12 +10,19 @@
 namespace V1_0 {
 
 struct BpExpression : public ::android::hardware::BpInterface<IHwExpression> {
-  explicit BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);
+    explicit BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);
 
-  virtual bool isRemote() const { return true; }
+    virtual bool isRemote() const { return true; }
 
-  // Methods from IExpression follow.
+    // Methods from IExpression follow.
+    ::android::hardware::Return<void> foo1(const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>& array)  override;
+    ::android::hardware::Return<void> foo2(const hidl_array<int32_t, 13 /* (5 + 8) */>& array)  override;
+    ::android::hardware::Return<void> foo3(const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>& array)  override;
 
+private:
+    // for hidl instrumentation.
+    std::vector<InstrumentationCallback> mInstrumentationCallbacks;
+    bool mEnableInstrumentation;
 };
 
 }  // namespace V1_0
diff --git a/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
index 064f030..1258224 100644
--- a/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
+++ b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
@@ -12,40 +12,273 @@
 constexpr hidl_version IExpression::version;
 
 BpExpression::BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
-    : BpInterface<IHwExpression>(_hidl_impl) {
+        : BpInterface<IHwExpression>(_hidl_impl) {
+        mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
+        registerInstrumentationCallbacks("android.hardware.tests.expression@1.0::IExpression", &mInstrumentationCallbacks);
+}
+
+::android::hardware::Return<void> BpExpression::foo1(const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>& array) {
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        args.push_back((void *)&array);
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+        }
+    }
+
+    ::android::hardware::Parcel _hidl_data;
+    ::android::hardware::Parcel _hidl_reply;
+    ::android::status_t _hidl_err;
+    ::android::hardware::Status _hidl_status;
+
+    _hidl_err = _hidl_data.writeInterfaceToken(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    size_t _hidl_array_parent;
+
+    _hidl_err = _hidl_data.writeBuffer(array.data(), 1 * sizeof(int32_t), &_hidl_array_parent);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = remote()->transact(::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO1, _hidl_data, &_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    if (!_hidl_status.isOk()) { return _hidl_status; }
+
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+        }
+    }
+
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>();
+
+_hidl_error:
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>(_hidl_status);
+}
+
+::android::hardware::Return<void> BpExpression::foo2(const hidl_array<int32_t, 13 /* (5 + 8) */>& array) {
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        args.push_back((void *)&array);
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+        }
+    }
+
+    ::android::hardware::Parcel _hidl_data;
+    ::android::hardware::Parcel _hidl_reply;
+    ::android::status_t _hidl_err;
+    ::android::hardware::Status _hidl_status;
+
+    _hidl_err = _hidl_data.writeInterfaceToken(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    size_t _hidl_array_parent;
+
+    _hidl_err = _hidl_data.writeBuffer(array.data(), 13 * sizeof(int32_t), &_hidl_array_parent);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = remote()->transact(::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO2, _hidl_data, &_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    if (!_hidl_status.isOk()) { return _hidl_status; }
+
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+        }
+    }
+
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>();
+
+_hidl_error:
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>(_hidl_status);
+}
+
+::android::hardware::Return<void> BpExpression::foo3(const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>& array) {
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        args.push_back((void *)&array);
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+        }
+    }
+
+    ::android::hardware::Parcel _hidl_data;
+    ::android::hardware::Parcel _hidl_reply;
+    ::android::status_t _hidl_err;
+    ::android::hardware::Status _hidl_status;
+
+    _hidl_err = _hidl_data.writeInterfaceToken(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    size_t _hidl_array_parent;
+
+    _hidl_err = _hidl_data.writeBuffer(array.data(), 20 * sizeof(int32_t), &_hidl_array_parent);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = remote()->transact(::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO3, _hidl_data, &_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
+    if (_hidl_err != ::android::OK) { goto _hidl_error; }
+
+    if (!_hidl_status.isOk()) { return _hidl_status; }
+
+    if (UNLIKELY(mEnableInstrumentation)) {
+        std::vector<void *> args;
+        for (auto callback: mInstrumentationCallbacks) {
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+        }
+    }
+
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>();
+
+_hidl_error:
+    _hidl_status.setFromStatusT(_hidl_err);
+    return ::android::hardware::Return<void>(_hidl_status);
 }
 
 IMPLEMENT_HWBINDER_META_INTERFACE(Expression, "android.hardware.tests.expression@1.0::IExpression");
 
 BnExpression::BnExpression(const ::android::sp<IExpression> &_hidl_impl)
-    : BnInterface<IExpression, IHwExpression>(_hidl_impl) {
-    enableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
-    registerInstrumentationCallbacks("android.hardware.tests.expression@1.0::IExpression", &instrumentationCallbacks);
+        : BnInterface<IExpression, IHwExpression>(_hidl_impl) {
+        mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
+        registerInstrumentationCallbacks("android.hardware.tests.expression@1.0::IExpression", &mInstrumentationCallbacks);
 }
 
 ::android::status_t BnExpression::onTransact(
-    uint32_t _hidl_code,
-    const ::android::hardware::Parcel &_hidl_data,
-    ::android::hardware::Parcel *_hidl_reply,
-    uint32_t _hidl_flags,
-    TransactCallback _hidl_cb) {
-  ::android::status_t _hidl_err = ::android::OK;
+        uint32_t _hidl_code,
+        const ::android::hardware::Parcel &_hidl_data,
+        ::android::hardware::Parcel *_hidl_reply,
+        uint32_t _hidl_flags,
+        TransactCallback _hidl_cb) {
+    ::android::status_t _hidl_err = ::android::OK;
 
-  switch (_hidl_code) {
-    default:
-    {
-      return ::android::hardware::BnInterface<IExpression, IHwExpression>::onTransact(
-          _hidl_code, _hidl_data, _hidl_reply, _hidl_flags, _hidl_cb);
+    switch (_hidl_code) {
+        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO1:
+        {
+            if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
+                _hidl_err = ::android::BAD_TYPE;
+                break;
+            }
+
+            const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>* array;
+
+            size_t _hidl_array_parent;
+
+            array = (const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>*)_hidl_data.readBuffer(&_hidl_array_parent);
+
+            if (array == nullptr) {
+                _hidl_err = ::android::UNKNOWN_ERROR;
+                break;
+            }
+
+            if (UNLIKELY(mEnableInstrumentation)) {
+                std::vector<void *> args;
+                args.push_back((void *)array);
+                for (auto callback: mInstrumentationCallbacks) {
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+                }
+            }
+
+            foo1(*array);
+
+            ::android::hardware::Status::ok().writeToParcel(_hidl_reply);
+            break;
+        }
+
+        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO2:
+        {
+            if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
+                _hidl_err = ::android::BAD_TYPE;
+                break;
+            }
+
+            const hidl_array<int32_t, 13 /* (5 + 8) */>* array;
+
+            size_t _hidl_array_parent;
+
+            array = (const hidl_array<int32_t, 13 /* (5 + 8) */>*)_hidl_data.readBuffer(&_hidl_array_parent);
+
+            if (array == nullptr) {
+                _hidl_err = ::android::UNKNOWN_ERROR;
+                break;
+            }
+
+            if (UNLIKELY(mEnableInstrumentation)) {
+                std::vector<void *> args;
+                args.push_back((void *)array);
+                for (auto callback: mInstrumentationCallbacks) {
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+                }
+            }
+
+            foo2(*array);
+
+            ::android::hardware::Status::ok().writeToParcel(_hidl_reply);
+            break;
+        }
+
+        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO3:
+        {
+            if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
+                _hidl_err = ::android::BAD_TYPE;
+                break;
+            }
+
+            const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>* array;
+
+            size_t _hidl_array_parent;
+
+            array = (const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>*)_hidl_data.readBuffer(&_hidl_array_parent);
+
+            if (array == nullptr) {
+                _hidl_err = ::android::UNKNOWN_ERROR;
+                break;
+            }
+
+            if (UNLIKELY(mEnableInstrumentation)) {
+                std::vector<void *> args;
+                args.push_back((void *)array);
+                for (auto callback: mInstrumentationCallbacks) {
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+                }
+            }
+
+            foo3(*array);
+
+            ::android::hardware::Status::ok().writeToParcel(_hidl_reply);
+            break;
+        }
+
+        default:
+        {
+            return ::android::hardware::BnInterface<IExpression, IHwExpression>::onTransact(
+                    _hidl_code, _hidl_data, _hidl_reply, _hidl_flags, _hidl_cb);
+        }
     }
-  }
 
-  if (_hidl_err == ::android::UNEXPECTED_NULL) {
-    _hidl_err = ::android::hardware::Status::fromExceptionCode(
-        ::android::hardware::Status::EX_NULL_POINTER)
-            .writeToParcel(_hidl_reply);
-  }
+    if (_hidl_err == ::android::UNEXPECTED_NULL) {
+        _hidl_err = ::android::hardware::Status::fromExceptionCode(
+                ::android::hardware::Status::EX_NULL_POINTER)
+                        .writeToParcel(_hidl_reply);
+    }
 
-  return _hidl_err;
+    return _hidl_err;
 }
 
 BsExpression::BsExpression(const sp<IExpression> impl) : mImpl(impl) {}
diff --git a/test/data/android/hardware/tests/expression/1.0/IExpression.h b/test/data/android/hardware/tests/expression/1.0/IExpression.h
index 2b2fd99..c11e389 100644
--- a/test/data/android/hardware/tests/expression/1.0/IExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.h
@@ -14,129 +14,190 @@
 namespace V1_0 {
 
 struct IExpression : virtual public RefBase {
-  enum class UInt64LiteralTypeGuessing : uint64_t {
-    noSuffixDec1 = 0ull, // (int32_t)0
-    noSuffixDec2 = 1ull, // (int32_t)1
-    noSuffixDec3 = 18446744073709551615ull, // (int32_t)(-1)
-    noSuffixDec4 = 18446744073709551615ull, // (int32_t)(~0)
-    noSuffixDec5 = 2147483647ull, // (int32_t)2147483647
-    noSuffixDec6 = 18446744071562067968ull, // (int64_t)(-2147483648)
-    noSuffixDec7 = 2147483648ull, // (int64_t)2147483648
-    noSuffixDec8 = 18446744071562067967ull, // (int64_t)(-2147483649)
-    noSuffixDec9 = 0ull, // (int32_t)(~(-1))
-    noSuffixHex1 = 2147483647ull, // (int32_t)0x7fffffff
-    noSuffixHex2 = 2147483648ull, // (uint32_t)0x80000000
-    noSuffixHex3 = 4294967295ull, // (uint32_t)0xffffffff
-    longHex1 = 4294967295ull, // (int64_t)0xffffffffl
-    longHex2 = 68719476735ull, // (int64_t)0xfffffffff
-    longHex3 = 9223372036854775807ull, // (int64_t)0x7fffffffffffffff
-    longHex4 = 9223372036854775808ull, // (uint64_t)0x8000000000000000
-    longHex5 = 18446744073709551615ull, // (uint64_t)0xFFFFFFFFFFFFFFFF
-  };
+    enum class UInt64LiteralTypeGuessing : uint64_t {
+        noSuffixDec1 = 0ull, // 0
+        noSuffixDec2 = 1ull, // 1
+        noSuffixDec3 = 18446744073709551615ull, // (-1)
+        noSuffixDec4 = 18446744073709551615ull, // (~0)
+        noSuffixDec5 = 2147483647ull, // 2147483647
+        noSuffixDec6 = 18446744071562067968ull, // (-2147483648)
+        noSuffixDec7 = 2147483648ull, // 2147483648
+        noSuffixDec8 = 18446744071562067967ull, // (-2147483649)
+        noSuffixDec9 = 0ull, // (~(-1))
+        noSuffixHex1 = 2147483647ull, // 0x7fffffff
+        noSuffixHex2 = 2147483648ull, // 0x80000000
+        noSuffixHex3 = 4294967295ull, // 0xffffffff
+        longHex1 = 4294967295ull, // 0xffffffffl
+        longHex2 = 68719476735ull, // 0xfffffffff
+        longHex3 = 9223372036854775807ull, // 0x7fffffffffffffff
+        longHex4 = 9223372036854775808ull, // 0x8000000000000000
+        longHex5 = 18446744073709551615ull, // 0xFFFFFFFFFFFFFFFF
+    };
 
-  enum class SuffixedLiteralTypeGuessing : int32_t {
-    decInt32_1 = 1, // (bool)((~(-1)) == 0)
-    decInt32_2 = 1, // (bool)((-(1 << 31)) == (1 << 31))
-    decInt64_1 = 1, // (bool)((~(-1l)) == 0)
-    decInt64_2 = 1, // (bool)((~4294967295) != 0)
-    decInt64_3 = 1, // (bool)((~4294967295l) != 0)
-    decInt64_4 = 1, // (bool)((-(1l << 63)) == (1l << 63))
-    hexInt32_1 = 1, // (bool)((-0x7fffffff) < 0)
-    hexUInt32_1 = 1, // (bool)((-0x80000000) > 0)
-    hexUInt32_2 = 1, // (bool)((~0xFFFFFFFF) == 0)
-    hexInt64_1 = 1, // (bool)((-0x7FFFFFFFFFFFFFFF) < 0)
-    hexUInt64_1 = 1, // (bool)((-0x8000000000000000) > 0)
-  };
+    enum class SuffixedLiteralTypeGuessing : int32_t {
+        decInt32_1 = 1, // ((~(-1)) == 0)
+        decInt32_2 = 1, // ((-(1 << 31)) == (1 << 31))
+        decInt64_1 = 1, // ((~(-1l)) == 0)
+        decInt64_2 = 1, // ((~4294967295) != 0)
+        decInt64_3 = 1, // ((~4294967295l) != 0)
+        decInt64_4 = 1, // ((-(1l << 63)) == (1l << 63))
+        hexInt32_1 = 1, // ((-0x7fffffff) < 0)
+        hexUInt32_1 = 1, // ((-0x80000000) > 0)
+        hexUInt32_2 = 1, // ((~0xFFFFFFFF) == 0)
+        hexInt64_1 = 1, // ((-0x7FFFFFFFFFFFFFFF) < 0)
+        hexUInt64_1 = 1, // ((-0x8000000000000000) > 0)
+    };
 
-  enum class Int64LiteralTypeGuessing : int64_t {
-    noSuffixDec11 = -2147483648ll, // (int32_t)(1 + 0x7fffffff)
-    noSuffixDec12 = 2147483647ll, // (uint32_t)(0x80000000 - 1)
-  };
+    enum class Int64LiteralTypeGuessing : int64_t {
+        noSuffixDec11 = -2147483648ll, // (1 + 0x7fffffff)
+        noSuffixDec12 = 2147483647ll, // (0x80000000 - 1)
+    };
 
-  enum class Int32BitShifting : int32_t {
-    int32BitShift1 = -2147483648, // (int32_t)(1 << 31)
-  };
+    enum class Int32BitShifting : int32_t {
+        int32BitShift1 = -2147483648, // (1 << 31)
+    };
 
-  enum class UInt32BitShifting : uint32_t {
-    uint32BitShift1 = 2147483648u, // (int32_t)(1 << 31)
-  };
+    enum class UInt32BitShifting : uint32_t {
+        uint32BitShift1 = 2147483648u, // (1 << 31)
+    };
 
-  enum class Int64BitShifting : int64_t {
-    int64BitShift1 = (int64_t)(-9223372036854775808ull), // (int64_t)(1l << 63)
-  };
+    enum class Int64BitShifting : int64_t {
+        int64BitShift1 = (int64_t)(-9223372036854775808ull), // (1l << 63)
+    };
 
-  enum class UInt64BitShifting : uint64_t {
-    uint64BitShift1 = 9223372036854775808ull, // (int64_t)(1l << 63)
-  };
+    enum class UInt64BitShifting : uint64_t {
+        uint64BitShift1 = 9223372036854775808ull, // (1l << 63)
+    };
 
-  enum class Precedence : int32_t {
-    literal = 4, // (int32_t)4
-    neg = -4, // (int32_t)(-4)
-    literalL = -4, // (int64_t)(-4L)
-    hex = -1, // (uint32_t)0xffffffff
-    hexLong = -1, // (int64_t)0xffffffffl
-    hexLong2 = -1, // (int64_t)0xfffffffff
-    simpleArithmetic = 5, // (int32_t)(4 + 1)
-    simpleArithmetic2 = 1, // (int32_t)((2 + 3) - 4)
-    simpleBoolExpr = 0, // (bool)(1 == 4)
-    simpleLogical = 1, // (bool)(1 && 1)
-    simpleComp = 1, // (bool)(1 < 2)
-    boolExpr1 = 0, // (bool)(!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
-    boolExpr = 0, // (bool)((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
-    simpleBitShift = 4, // (int32_t)(1 << 2)
-    simpleBitShift2 = 2, // (int32_t)(4 >> 1)
-    simpleBitShiftNeg = 2, // (int32_t)(4 << (-1))
-    simpleArithmeticRightShift = -1, // (int32_t)((1 << 31) >> 31)
-    simpleBitExpr = 5, // (int32_t)(1 | (16 >> 2))
-    bitExpr = 3, // (int32_t)(((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
-    arithmeticExpr = 33, // (int32_t)((2 + 3) - ((4 * (-7)) / (10 % 3)))
-    messyExpr = 2, // (int32_t)(2 + ((-3) & (4 / 7)))
-    paranExpr = 2, // (int32_t)(1 + 1)
-    ternary = 2, // (int32_t)(1?2:3)
-    ternary2 = 3, // (int32_t)((1 && 2)?3:4)
-    complicatedTernary2 = 56, // (int32_t)((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
-  };
+    enum class Precedence : int32_t {
+        literal = 4,
+        neg = -4, // (-4)
+        literalL = -4, // (-4L)
+        hex = -1, // 0xffffffff
+        hexLong = -1, // 0xffffffffl
+        hexLong2 = -1, // 0xfffffffff
+        simpleArithmetic = 5, // (4 + 1)
+        simpleArithmetic2 = 1, // ((2 + 3) - 4)
+        simpleBoolExpr = 0, // (1 == 4)
+        simpleLogical = 1, // (1 && 1)
+        simpleComp = 1, // (1 < 2)
+        boolExpr1 = 0, // (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
+        boolExpr = 0, // ((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
+        simpleBitShift = 4, // (1 << 2)
+        simpleBitShift2 = 2, // (4 >> 1)
+        simpleBitShiftNeg = 2, // (4 << (-1))
+        simpleArithmeticRightShift = -1, // ((1 << 31) >> 31)
+        simpleBitExpr = 5, // (1 | (16 >> 2))
+        bitExpr = 3, // (((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
+        arithmeticExpr = 33, // ((2 + 3) - ((4 * (-7)) / (10 % 3)))
+        messyExpr = 2, // (2 + ((-3) & (4 / 7)))
+        paranExpr = 2, // (1 + 1)
+        ternary = 2, // (1?2:3)
+        ternary2 = 3, // ((1 && 2)?3:4)
+        complicatedTernary2 = 56, // ((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
+    };
 
-  enum class OperatorSanityCheck : int32_t {
-    plus = 1, // (bool)((1 + 2) == 3)
-    minus = 1, // (bool)((8 - 9) == (-1))
-    product = 1, // (bool)((9 * 9) == 81)
-    division = 1, // (bool)((29 / 3) == 9)
-    mod = 1, // (bool)((29 % 3) == 2)
-    bit_or = 1, // (bool)((0xC0010000 | 0xF00D) == 0xC001F00D)
-    bit_or2 = 1, // (bool)((10 | 6) == 14)
-    bit_and = 1, // (bool)((10 & 6) == 2)
-    bit_xor = 1, // (bool)((10 ^ 6) == 12)
-    lt1 = 1, // (bool)(6 < 10)
-    lt2 = 1, // (bool)((10 < 10) == 0)
-    gt1 = 1, // (bool)((6 > 10) == 0)
-    gt2 = 1, // (bool)((10 > 10) == 0)
-    gte1 = 1, // (bool)(19 >= 10)
-    gte2 = 1, // (bool)(10 >= 10)
-    lte1 = 1, // (bool)(5 <= 10)
-    lte2 = 1, // (bool)((19 <= 10) == 0)
-    ne1 = 1, // (bool)(19 != 10)
-    ne2 = 1, // (bool)((10 != 10) == 0)
-    lshift = 1, // (bool)((22 << 1) == 44)
-    rshift = 1, // (bool)((11 >> 1) == 5)
-    logor1 = 1, // (bool)((1 || 0) == 1)
-    logor2 = 1, // (bool)((1 || 1) == 1)
-    logor3 = 1, // (bool)((0 || 0) == 0)
-    logor4 = 1, // (bool)((0 || 1) == 1)
-    logand1 = 1, // (bool)((1 && 0) == 0)
-    logand2 = 1, // (bool)((1 && 1) == 1)
-    logand3 = 1, // (bool)((0 && 0) == 0)
-    logand4 = 1, // (bool)((0 && 1) == 0)
-  };
+    enum class OperatorSanityCheck : int32_t {
+        plus = 1, // ((1 + 2) == 3)
+        minus = 1, // ((8 - 9) == (-1))
+        product = 1, // ((9 * 9) == 81)
+        division = 1, // ((29 / 3) == 9)
+        mod = 1, // ((29 % 3) == 2)
+        bit_or = 1, // ((0xC0010000 | 0xF00D) == 0xC001F00D)
+        bit_or2 = 1, // ((10 | 6) == 14)
+        bit_and = 1, // ((10 & 6) == 2)
+        bit_xor = 1, // ((10 ^ 6) == 12)
+        lt1 = 1, // (6 < 10)
+        lt2 = 1, // ((10 < 10) == 0)
+        gt1 = 1, // ((6 > 10) == 0)
+        gt2 = 1, // ((10 > 10) == 0)
+        gte1 = 1, // (19 >= 10)
+        gte2 = 1, // (10 >= 10)
+        lte1 = 1, // (5 <= 10)
+        lte2 = 1, // ((19 <= 10) == 0)
+        ne1 = 1, // (19 != 10)
+        ne2 = 1, // ((10 != 10) == 0)
+        lshift = 1, // ((22 << 1) == 44)
+        rshift = 1, // ((11 >> 1) == 5)
+        logor1 = 1, // ((1 || 0) == 1)
+        logor2 = 1, // ((1 || 1) == 1)
+        logor3 = 1, // ((0 || 0) == 0)
+        logor4 = 1, // ((0 || 1) == 1)
+        logand1 = 1, // ((1 && 0) == 0)
+        logand2 = 1, // ((1 && 1) == 1)
+        logand3 = 1, // ((0 && 0) == 0)
+        logand4 = 1, // ((0 && 1) == 0)
+    };
 
-  constexpr static hidl_version version = {1,0};
-  virtual const hidl_version& getInterfaceVersion() const {
-    return version;
-  }
+    enum class Grayscale : int8_t {
+        WHITE = 126,
+        GRAY = 127,
+        DARK_GRAY = -128, // 128
+        BLACK = -127, // 129
+    };
 
-  virtual bool isRemote() const { return false; }
+    enum class Color : int8_t {
+        WHITE = 126,
+        GRAY = 127,
+        DARK_GRAY = -128, // 128
+        BLACK = -127, // 129
+        RED = -126, // 130
+        RUBY = 0,
+        GREEN = 1,
+        BLUE = 5,
+        CYAN = 6,
+        ORANGE = 7,
+        ROSE = 126, // WHITE
+    };
 
-  DECLARE_REGISTER_AND_GET_SERVICE(Expression)
+    enum class Foo1 : int8_t {
+    };
+
+    enum class Foo2 : int8_t {
+    };
+
+    enum class Foo3 : int8_t {
+        BAR1 = 0,
+        BAR2 = 10,
+    };
+
+    enum class Foo4 : int8_t {
+        BAR1 = 0,
+        BAR2 = 10,
+        BAR3 = 11,
+        BAR4 = 21, // (BAR2 + BAR3)
+    };
+
+    enum class Number : uint8_t {
+        MAX = 255,
+        MAX_PLUS_1 = 0, // 256
+        MAX_PLUS_2 = 1, // 257
+    };
+
+    enum class Constants : int32_t {
+        CONST_FOO = 0,
+        CONST_BAR = 70,
+        MAX_ARRAY_SIZE = 20,
+        MAX_ARRAY_SIZE2 = 21,
+        MAX_ARRAY_SIZE3 = 40, // (MAX_ARRAY_SIZE + MAX_ARRAY_SIZE)
+        MY_INT32_MAX_MINUS_1 = 2147483646, // 0x7FFFFFFE
+        MY_INT32_MAX = 2147483647,
+        MY_INT32_MIN = -2147483648,
+        MY_INT32_MIN_PLUS_1 = -2147483647,
+    };
+
+    constexpr static hidl_version version = {1,0};
+    virtual const hidl_version& getInterfaceVersion() const {
+        return version;
+    }
+
+    virtual bool isRemote() const { return false; }
+
+    // @callflow(key=1 /* (Constants:CONST_FOO + 1) */)
+    virtual ::android::hardware::Return<void> foo1(const hidl_array<int32_t, 1 /* (Constants:CONST_FOO + 1) */>& array) = 0;
+    virtual ::android::hardware::Return<void> foo2(const hidl_array<int32_t, 13 /* (5 + 8) */>& array) = 0;
+    virtual ::android::hardware::Return<void> foo3(const hidl_array<int32_t, 20 /* Constants:MAX_ARRAY_SIZE */>& array) = 0;
+    DECLARE_REGISTER_AND_GET_SERVICE(Expression)
 };
 
 }  // namespace V1_0
diff --git a/test/data/android/hardware/tests/expression/1.0/IHwExpression.h b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
index 70b5f7d..6294eb8 100644
--- a/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
@@ -16,11 +16,14 @@
 namespace V1_0 {
 
 struct IHwExpression : public IExpression, public ::android::hardware::IInterface {
-  DECLARE_HWBINDER_META_INTERFACE(Expression);
+    DECLARE_HWBINDER_META_INTERFACE(Expression);
 
-  enum Call {
-    CallCount
-  };
+    enum Call {
+        FOO1 = ::android::hardware::IBinder::FIRST_CALL_TRANSACTION,
+        FOO2,
+        FOO3,
+        CallCount
+    };
 
 };