Merge "And one more backend for hidl-gen to create a simple static java library"
diff --git a/AST.h b/AST.h
index 1f9b02f..ddba36c 100644
--- a/AST.h
+++ b/AST.h
@@ -228,12 +228,6 @@
             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/CompoundType.cpp b/CompoundType.cpp
index 63514d8..eb5d083 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -133,12 +133,11 @@
             << name
             << " == nullptr) {\n";
 
-        out.indent();
+        out.indentBlock([&]{
+            out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
+            handleError2(out, mode);
+        });
 
-        out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
-        handleError2(out, mode);
-
-        out.unindent();
         out << "}\n\n";
     } else {
         out << "_hidl_err = "
@@ -313,19 +312,14 @@
             << "writeEmbeddedReferenceToParcel(\n";
     }
 
-    out.indent();
-    out.indent();
-
-    out << (isReader ? parcelObjDeref : parcelObjPointer);
-    out << ",\n"
-        << parentName
-        << ",\n"
-        << offsetText;
-
-    out << ");\n\n";
-
-    out.unindent();
-    out.unindent();
+    out.indentBlock(2, [&]{
+        out << (isReader ? parcelObjDeref : parcelObjPointer)
+            << ",\n"
+            << parentName
+            << ",\n"
+            << offsetText
+            << ");\n\n";
+    });
 
     handleError(out, mode);
 }
@@ -352,41 +346,37 @@
     if (needsEmbeddedReadWrite()) {
         out << "\n::android::status_t readEmbeddedFromParcel(\n";
 
-        out.indent();
-        out.indent();
+        out.indent(2);
 
         out << "const ::android::hardware::Parcel &parcel,\n"
                   << "size_t parentHandle,\n"
                   << "size_t parentOffset);\n\n";
 
-        out.unindent();
-        out.unindent();
+        out.unindent(2);
 
         out << "::android::status_t writeEmbeddedToParcel(\n";
 
-        out.indent();
-        out.indent();
+        out.indent(2);
 
         out << "::android::hardware::Parcel *parcel,\n"
                   << "size_t parentHandle,\n"
                   << "size_t parentOffset) const;\n";
 
-        out.unindent();
-        out.unindent();
+        out.unindent(2);
     }
 
     if(needsResolveReferences()) {
         out << "\n";
         out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
-        out.indent(); out.indent();
+        out.indent(2);
         out << "const ::android::hardware::Parcel &parcel,\n"
             << "size_t parentHandle, size_t parentOffset);\n";
-        out.unindent(); out.unindent();
+        out.unindent(2);
         out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
-        out.indent(); out.indent();
+        out.indent(2);
         out << "::android::hardware::Parcel *,\n"
             << "size_t parentHandle, size_t parentOffset) const;\n";
-        out.unindent(); out.unindent();
+        out.unindent(2);
     }
 
     out.unindent();
@@ -483,8 +473,7 @@
     ////////////////////////////////////////////////////////////////////////////
 
     out << "public final void readEmbeddedFromParcel(\n";
-    out.indent();
-    out.indent();
+    out.indent(2);
     out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
     out.unindent();
 
@@ -534,8 +523,7 @@
     ////////////////////////////////////////////////////////////////////////////
 
     out << "public static final void writeVectorToParcel(\n";
-    out.indent();
-    out.indent();
+    out.indent(2);
     out << "HwParcel parcel, ArrayList<"
         << localName()
         << "> _hidl_vec) {\n";
@@ -561,8 +549,7 @@
     ////////////////////////////////////////////////////////////////////////////
 
     out << "public final void writeEmbeddedToBlob(\n";
-    out.indent();
-    out.indent();
+    out.indent(2);
     out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
     out.unindent();
 
@@ -606,8 +593,7 @@
                            : "::writeEmbeddedToParcel")
               << "(\n";
 
-    out.indent();
-    out.indent();
+    out.indent(2);
 
     if (isReader) {
         out << "const ::android::hardware::Parcel &parcel,\n";
@@ -624,8 +610,7 @@
 
     out << " {\n";
 
-    out.unindent();
-    out.unindent();
+    out.unindent(2);
     out.indent();
 
     out << "::android::status_t _hidl_err = ::android::OK;\n\n";
@@ -682,18 +667,18 @@
 
     if (isReader) {
         out << "::readEmbeddedReferenceFromParcel(\n";
-        out.indent(); out.indent();
+        out.indent(2);
         out << "const ::android::hardware::Parcel &parcel,\n"
             << "size_t " << parentHandleName << ", "
             << "size_t " << parentOffsetName << ")\n";
-        out.unindent(); out.unindent();
+        out.unindent(2);
     } else {
         out << "::writeEmbeddedReferenceToParcel(\n";
-        out.indent(); out.indent();
+        out.indent(2);
         out << "::android::hardware::Parcel *parcel,\n"
             << "size_t " << parentHandleName << ", "
             << "size_t " << parentOffsetName << ") const\n";
-        out.unindent(); out.unindent();
+        out.unindent(2);
     }
 
     out << " {\n";
diff --git a/generateCpp.cpp b/generateCpp.cpp
index c514714..fdca7fc 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -615,7 +615,7 @@
         << baseName
         << " : public ::android::hardware::BnInterface<I"
         << baseName << ", IHw" << baseName
-        << "> {\n";
+        << ">, public ::android::hardware::HidlInstrumentor {\n";
 
     out.indent();
     out << "explicit Bn"
@@ -644,12 +644,6 @@
 
 
     out.unindent();
-    out << "private:\n";
-
-    out.indent();
-    emitCppInstrumentationDecl(out);
-    out.unindent();
-
     out << "};\n\n";
 
     enterLeaveNamespace(out, false /* enter */);
@@ -708,7 +702,7 @@
         << baseName
         << " : public ::android::hardware::BpInterface<IHw"
         << baseName
-        << "> {\n";
+        << ">, public ::android::hardware::HidlInstrumentor {\n";
 
     out.indent();
 
@@ -729,13 +723,6 @@
     }
 
     out.unindent();
-    out << "private:\n";
-
-    out.indent();
-    emitCppInstrumentationDecl(out);
-
-    out.unindent();
-
     out << "};\n\n";
 
     enterLeaveNamespace(out, false /* enter */);
@@ -794,7 +781,6 @@
         out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
         out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
         out << "#include <" << prefix << "/Bs" << baseName << ".h>\n";
-        out << "#include <cutils/properties.h>\n";
     } else {
         out << "#include <" << prefix << "types.h>\n";
     }
@@ -931,9 +917,12 @@
     out << ": BpInterface"
         << "<IHw"
         << baseName
-        << ">(_hidl_impl) {\n";
-
-    emitCppInstrumentationInit(out, baseName);
+        << ">(_hidl_impl),\n"
+        << "  HidlInstrumentor(\""
+        << mPackage.string()
+        << "::I"
+        << baseName
+        << "\") {\n";
 
     out.unindent();
     out.unindent();
@@ -1144,9 +1133,13 @@
         << baseName
         << ", IHw"
         << baseName
-        << ">(_hidl_impl) {\n";
+        << ">(_hidl_impl),\n"
+        << "  HidlInstrumentor(\""
+        << mPackage.string()
+        << "::I"
+        << baseName
+        << "\") {\n";
 
-    emitCppInstrumentationInit(out, baseName);
     out.unindent();
     out.unindent();
     out << "}\n\n";
@@ -1628,14 +1621,14 @@
         const Interface *iface, const Method *method) const {
     out << "if (UNLIKELY(mEnableInstrumentation)) {\n";
     out.indent();
-    out << "std::vector<void *> args;\n";
+    out << "std::vector<void *> _hidl_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 *)"
+                out << "_hidl_args.push_back((void *)"
                     << (arg->type().resultNeedsDeref() ? "" : "&")
                     << arg->name()
                     << ");\n";
@@ -1647,11 +1640,13 @@
             event_str = "InstrumentationEvent::SERVER_API_EXIT";
             const TypedVar *elidedReturn = method->canElideCallback();
             if (elidedReturn != nullptr) {
-                out << "args.push_back((void *)&" << elidedReturn->name()
+                out << "_hidl_args.push_back((void *)&"
+                    << elidedReturn->name()
                     << ");\n";
             } else {
                 for (const auto &arg : method->results()) {
-                    out << "args.push_back((void *)&" << arg->name()
+                    out << "_hidl_args.push_back((void *)&"
+                        << arg->name()
                         << ");\n";
                 }
             }
@@ -1661,7 +1656,9 @@
         {
             event_str = "InstrumentationEvent::CLIENT_API_ENTRY";
             for (const auto &arg : method->args()) {
-                out << "args.push_back((void *)&" << arg->name() << ");\n";
+                out << "_hidl_args.push_back((void *)&"
+                    << arg->name()
+                    << ");\n";
             }
             break;
         }
@@ -1669,9 +1666,10 @@
         {
             event_str = "InstrumentationEvent::CLIENT_API_EXIT";
             for (const auto &arg : method->results()) {
-                out << "args.push_back((void *)"
+                out << "_hidl_args.push_back((void *)"
                     << (arg->type().resultNeedsDeref() ? "" : "&")
-                    << "_hidl_out_" << arg->name()
+                    << "_hidl_out_"
+                    << arg->name()
                     << ");\n";
             }
             break;
@@ -1698,7 +1696,7 @@
         << iface->localName()
         << "\", \""
         << method->name()
-        << "\", &args);\n";
+        << "\", &_hidl_args);\n";
     out.unindent();
     out << "}\n";
     out.unindent();
@@ -1707,23 +1705,5 @@
     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/test/Android.bp b/test/Android.bp
index b64913b..77c47f1 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -8,8 +8,10 @@
         "liblog",
         "libcutils",
         "libhidl",
+        "libfootest",
         "libhwbinder",
         "libnativehelper",
+        "libpointertest",
         "libutils",
         "android.hardware.tests.foo@1.0",
         "android.hardware.tests.bar@1.0",
@@ -17,6 +19,17 @@
     ],
     static_libs: ["libgtest"],
 
+    required: [
+        // Warning, these should never be specified explicitly for anything else
+        // as for a given device, what hal implementation is used is determined
+        // by what is specified/available in a device.mk. However, this test
+        // actually depends on these test implementations (which should never be
+        // included on a device.mk).
+        "android.hardware.tests.foo@1.0-impl",
+        "android.hardware.tests.bar@1.0-impl",
+        "android.hardware.tests.pointer@1.0-impl",
+    ],
+
     cflags: [
         "-O0",
         "-g",
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 0fcecb1..975be4a 100644
--- a/test/data/android/hardware/tests/expression/1.0/BnExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
@@ -9,7 +9,7 @@
 namespace expression {
 namespace V1_0 {
 
-struct BnExpression : public ::android::hardware::BnInterface<IExpression, IHwExpression> {
+struct BnExpression : public ::android::hardware::BnInterface<IExpression, IHwExpression>, public ::android::hardware::HidlInstrumentor {
     explicit BnExpression(const ::android::sp<IExpression> &_hidl_impl);
 
     ::android::status_t onTransact(
@@ -30,10 +30,6 @@
         return mImpl->foo3(array);
     };
 
-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 33e4b91..b447cf3 100644
--- a/test/data/android/hardware/tests/expression/1.0/BpExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
@@ -9,7 +9,7 @@
 namespace expression {
 namespace V1_0 {
 
-struct BpExpression : public ::android::hardware::BpInterface<IHwExpression> {
+struct BpExpression : public ::android::hardware::BpInterface<IHwExpression>, public ::android::hardware::HidlInstrumentor {
     explicit BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);
 
     virtual bool isRemote() const { return true; }
@@ -19,10 +19,6 @@
     ::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 1258224..b66cfb4 100644
--- a/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
+++ b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
@@ -1,7 +1,6 @@
 #include <android/hardware/tests/expression/1.0//BpExpression.h>
 #include <android/hardware/tests/expression/1.0//BnExpression.h>
 #include <android/hardware/tests/expression/1.0//BsExpression.h>
-#include <cutils/properties.h>
 
 namespace android {
 namespace hardware {
@@ -12,17 +11,16 @@
 constexpr hidl_version IExpression::version;
 
 BpExpression::BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
-        : BpInterface<IHwExpression>(_hidl_impl) {
-        mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
-        registerInstrumentationCallbacks("android.hardware.tests.expression@1.0::IExpression", &mInstrumentationCallbacks);
+        : BpInterface<IHwExpression>(_hidl_impl),
+          HidlInstrumentor("android.hardware.tests.expression@1.0::IExpression") {
 }
 
 ::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);
+        std::vector<void *> _hidl_args;
+        _hidl_args.push_back((void *)&array);
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &_hidl_args);
         }
     }
 
@@ -39,7 +37,7 @@
     _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);
+    _hidl_err = remote()->transact(1 /* foo1 */, _hidl_data, &_hidl_reply);
     if (_hidl_err != ::android::OK) { goto _hidl_error; }
 
     _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
@@ -48,9 +46,9 @@
     if (!_hidl_status.isOk()) { return _hidl_status; }
 
     if (UNLIKELY(mEnableInstrumentation)) {
-        std::vector<void *> args;
+        std::vector<void *> _hidl_args;
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &_hidl_args);
         }
     }
 
@@ -64,10 +62,10 @@
 
 ::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);
+        std::vector<void *> _hidl_args;
+        _hidl_args.push_back((void *)&array);
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &_hidl_args);
         }
     }
 
@@ -84,7 +82,7 @@
     _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);
+    _hidl_err = remote()->transact(2 /* foo2 */, _hidl_data, &_hidl_reply);
     if (_hidl_err != ::android::OK) { goto _hidl_error; }
 
     _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
@@ -93,9 +91,9 @@
     if (!_hidl_status.isOk()) { return _hidl_status; }
 
     if (UNLIKELY(mEnableInstrumentation)) {
-        std::vector<void *> args;
+        std::vector<void *> _hidl_args;
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &_hidl_args);
         }
     }
 
@@ -109,10 +107,10 @@
 
 ::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);
+        std::vector<void *> _hidl_args;
+        _hidl_args.push_back((void *)&array);
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+            callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &_hidl_args);
         }
     }
 
@@ -129,7 +127,7 @@
     _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);
+    _hidl_err = remote()->transact(3 /* foo3 */, _hidl_data, &_hidl_reply);
     if (_hidl_err != ::android::OK) { goto _hidl_error; }
 
     _hidl_err = _hidl_status.readFromParcel(_hidl_reply);
@@ -138,9 +136,9 @@
     if (!_hidl_status.isOk()) { return _hidl_status; }
 
     if (UNLIKELY(mEnableInstrumentation)) {
-        std::vector<void *> args;
+        std::vector<void *> _hidl_args;
         for (auto callback: mInstrumentationCallbacks) {
-            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+            callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &_hidl_args);
         }
     }
 
@@ -155,9 +153,8 @@
 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) {
-        mEnableInstrumentation = property_get_bool("hal.instrumentation.enable", false);
-        registerInstrumentationCallbacks("android.hardware.tests.expression@1.0::IExpression", &mInstrumentationCallbacks);
+        : BnInterface<IExpression, IHwExpression>(_hidl_impl),
+          HidlInstrumentor("android.hardware.tests.expression@1.0::IExpression") {
 }
 
 ::android::status_t BnExpression::onTransact(
@@ -169,7 +166,7 @@
     ::android::status_t _hidl_err = ::android::OK;
 
     switch (_hidl_code) {
-        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO1:
+        case 1 /* foo1 */:
         {
             if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
                 _hidl_err = ::android::BAD_TYPE;
@@ -188,10 +185,10 @@
             }
 
             if (UNLIKELY(mEnableInstrumentation)) {
-                std::vector<void *> args;
-                args.push_back((void *)array);
+                std::vector<void *> _hidl_args;
+                _hidl_args.push_back((void *)array);
                 for (auto callback: mInstrumentationCallbacks) {
-                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &args);
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo1", &_hidl_args);
                 }
             }
 
@@ -201,7 +198,7 @@
             break;
         }
 
-        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO2:
+        case 2 /* foo2 */:
         {
             if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
                 _hidl_err = ::android::BAD_TYPE;
@@ -220,10 +217,10 @@
             }
 
             if (UNLIKELY(mEnableInstrumentation)) {
-                std::vector<void *> args;
-                args.push_back((void *)array);
+                std::vector<void *> _hidl_args;
+                _hidl_args.push_back((void *)array);
                 for (auto callback: mInstrumentationCallbacks) {
-                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &args);
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo2", &_hidl_args);
                 }
             }
 
@@ -233,7 +230,7 @@
             break;
         }
 
-        case ::android::hardware::tests::expression::V1_0::IHwExpression::Call::FOO3:
+        case 3 /* foo3 */:
         {
             if (!_hidl_data.enforceInterface(::android::hardware::tests::expression::V1_0::IHwExpression::descriptor)) {
                 _hidl_err = ::android::BAD_TYPE;
@@ -252,10 +249,10 @@
             }
 
             if (UNLIKELY(mEnableInstrumentation)) {
-                std::vector<void *> args;
-                args.push_back((void *)array);
+                std::vector<void *> _hidl_args;
+                _hidl_args.push_back((void *)array);
                 for (auto callback: mInstrumentationCallbacks) {
-                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &args);
+                    callback(InstrumentationEvent::SERVER_API_ENTRY, "android.hardware.tests.expression", "1.0", "IExpression", "foo3", &_hidl_args);
                 }
             }
 
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 c11e389..e7433b8 100644
--- a/test/data/android/hardware/tests/expression/1.0/IExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.h
@@ -28,7 +28,7 @@
         noSuffixHex2 = 2147483648ull, // 0x80000000
         noSuffixHex3 = 4294967295ull, // 0xffffffff
         longHex1 = 4294967295ull, // 0xffffffffl
-        longHex2 = 68719476735ull, // 0xfffffffff
+        longHex2 = 68719476735ull, // 0Xfffffffff
         longHex3 = 9223372036854775807ull, // 0x7fffffffffffffff
         longHex4 = 9223372036854775808ull, // 0x8000000000000000
         longHex5 = 18446744073709551615ull, // 0xFFFFFFFFFFFFFFFF
@@ -200,6 +200,228 @@
     DECLARE_REGISTER_AND_GET_SERVICE(Expression)
 };
 
+inline IExpression::UInt64LiteralTypeGuessing operator|(
+        IExpression::UInt64LiteralTypeGuessing lhs, IExpression::UInt64LiteralTypeGuessing rhs) {
+    return static_cast<IExpression::UInt64LiteralTypeGuessing>(
+            static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
+}
+
+inline IExpression::UInt64LiteralTypeGuessing & operator|=(
+        IExpression::UInt64LiteralTypeGuessing &lhs, IExpression::UInt64LiteralTypeGuessing rhs) {
+    lhs = static_cast<IExpression::UInt64LiteralTypeGuessing>(
+            static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::SuffixedLiteralTypeGuessing operator|(
+        IExpression::SuffixedLiteralTypeGuessing lhs, IExpression::SuffixedLiteralTypeGuessing rhs) {
+    return static_cast<IExpression::SuffixedLiteralTypeGuessing>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+}
+
+inline IExpression::SuffixedLiteralTypeGuessing & operator|=(
+        IExpression::SuffixedLiteralTypeGuessing &lhs, IExpression::SuffixedLiteralTypeGuessing rhs) {
+    lhs = static_cast<IExpression::SuffixedLiteralTypeGuessing>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Int64LiteralTypeGuessing operator|(
+        IExpression::Int64LiteralTypeGuessing lhs, IExpression::Int64LiteralTypeGuessing rhs) {
+    return static_cast<IExpression::Int64LiteralTypeGuessing>(
+            static_cast<int64_t>(lhs) | static_cast<int64_t>(rhs));
+}
+
+inline IExpression::Int64LiteralTypeGuessing & operator|=(
+        IExpression::Int64LiteralTypeGuessing &lhs, IExpression::Int64LiteralTypeGuessing rhs) {
+    lhs = static_cast<IExpression::Int64LiteralTypeGuessing>(
+            static_cast<int64_t>(lhs) | static_cast<int64_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Int32BitShifting operator|(
+        IExpression::Int32BitShifting lhs, IExpression::Int32BitShifting rhs) {
+    return static_cast<IExpression::Int32BitShifting>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+}
+
+inline IExpression::Int32BitShifting & operator|=(
+        IExpression::Int32BitShifting &lhs, IExpression::Int32BitShifting rhs) {
+    lhs = static_cast<IExpression::Int32BitShifting>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::UInt32BitShifting operator|(
+        IExpression::UInt32BitShifting lhs, IExpression::UInt32BitShifting rhs) {
+    return static_cast<IExpression::UInt32BitShifting>(
+            static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
+}
+
+inline IExpression::UInt32BitShifting & operator|=(
+        IExpression::UInt32BitShifting &lhs, IExpression::UInt32BitShifting rhs) {
+    lhs = static_cast<IExpression::UInt32BitShifting>(
+            static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Int64BitShifting operator|(
+        IExpression::Int64BitShifting lhs, IExpression::Int64BitShifting rhs) {
+    return static_cast<IExpression::Int64BitShifting>(
+            static_cast<int64_t>(lhs) | static_cast<int64_t>(rhs));
+}
+
+inline IExpression::Int64BitShifting & operator|=(
+        IExpression::Int64BitShifting &lhs, IExpression::Int64BitShifting rhs) {
+    lhs = static_cast<IExpression::Int64BitShifting>(
+            static_cast<int64_t>(lhs) | static_cast<int64_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::UInt64BitShifting operator|(
+        IExpression::UInt64BitShifting lhs, IExpression::UInt64BitShifting rhs) {
+    return static_cast<IExpression::UInt64BitShifting>(
+            static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
+}
+
+inline IExpression::UInt64BitShifting & operator|=(
+        IExpression::UInt64BitShifting &lhs, IExpression::UInt64BitShifting rhs) {
+    lhs = static_cast<IExpression::UInt64BitShifting>(
+            static_cast<uint64_t>(lhs) | static_cast<uint64_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Precedence operator|(
+        IExpression::Precedence lhs, IExpression::Precedence rhs) {
+    return static_cast<IExpression::Precedence>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+}
+
+inline IExpression::Precedence & operator|=(
+        IExpression::Precedence &lhs, IExpression::Precedence rhs) {
+    lhs = static_cast<IExpression::Precedence>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::OperatorSanityCheck operator|(
+        IExpression::OperatorSanityCheck lhs, IExpression::OperatorSanityCheck rhs) {
+    return static_cast<IExpression::OperatorSanityCheck>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+}
+
+inline IExpression::OperatorSanityCheck & operator|=(
+        IExpression::OperatorSanityCheck &lhs, IExpression::OperatorSanityCheck rhs) {
+    lhs = static_cast<IExpression::OperatorSanityCheck>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Grayscale operator|(
+        IExpression::Grayscale lhs, IExpression::Grayscale rhs) {
+    return static_cast<IExpression::Grayscale>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Grayscale & operator|=(
+        IExpression::Grayscale &lhs, IExpression::Grayscale rhs) {
+    lhs = static_cast<IExpression::Grayscale>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Color operator|(
+        IExpression::Color lhs, IExpression::Color rhs) {
+    return static_cast<IExpression::Color>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Color & operator|=(
+        IExpression::Color &lhs, IExpression::Color rhs) {
+    lhs = static_cast<IExpression::Color>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Foo1 operator|(
+        IExpression::Foo1 lhs, IExpression::Foo1 rhs) {
+    return static_cast<IExpression::Foo1>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Foo1 & operator|=(
+        IExpression::Foo1 &lhs, IExpression::Foo1 rhs) {
+    lhs = static_cast<IExpression::Foo1>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Foo2 operator|(
+        IExpression::Foo2 lhs, IExpression::Foo2 rhs) {
+    return static_cast<IExpression::Foo2>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Foo2 & operator|=(
+        IExpression::Foo2 &lhs, IExpression::Foo2 rhs) {
+    lhs = static_cast<IExpression::Foo2>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Foo3 operator|(
+        IExpression::Foo3 lhs, IExpression::Foo3 rhs) {
+    return static_cast<IExpression::Foo3>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Foo3 & operator|=(
+        IExpression::Foo3 &lhs, IExpression::Foo3 rhs) {
+    lhs = static_cast<IExpression::Foo3>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Foo4 operator|(
+        IExpression::Foo4 lhs, IExpression::Foo4 rhs) {
+    return static_cast<IExpression::Foo4>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+}
+
+inline IExpression::Foo4 & operator|=(
+        IExpression::Foo4 &lhs, IExpression::Foo4 rhs) {
+    lhs = static_cast<IExpression::Foo4>(
+            static_cast<int8_t>(lhs) | static_cast<int8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Number operator|(
+        IExpression::Number lhs, IExpression::Number rhs) {
+    return static_cast<IExpression::Number>(
+            static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
+}
+
+inline IExpression::Number & operator|=(
+        IExpression::Number &lhs, IExpression::Number rhs) {
+    lhs = static_cast<IExpression::Number>(
+            static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs));
+    return lhs;
+}
+
+inline IExpression::Constants operator|(
+        IExpression::Constants lhs, IExpression::Constants rhs) {
+    return static_cast<IExpression::Constants>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+}
+
+inline IExpression::Constants & operator|=(
+        IExpression::Constants &lhs, IExpression::Constants rhs) {
+    lhs = static_cast<IExpression::Constants>(
+            static_cast<int32_t>(lhs) | static_cast<int32_t>(rhs));
+    return lhs;
+}
+
+
 }  // namespace V1_0
 }  // namespace expression
 }  // namespace tests
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 6294eb8..e5852aa 100644
--- a/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
+++ b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
@@ -18,13 +18,6 @@
 struct IHwExpression : public IExpression, public ::android::hardware::IInterface {
     DECLARE_HWBINDER_META_INTERFACE(Expression);
 
-    enum Call {
-        FOO1 = ::android::hardware::IBinder::FIRST_CALL_TRANSACTION,
-        FOO2,
-        FOO3,
-        CallCount
-    };
-
 };
 
 }  // namespace V1_0
diff --git a/test/main.cpp b/test/main.cpp
index 18c6bac..997fcc6 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -23,6 +23,9 @@
 #include <sstream>
 #include <vector>
 
+#include <hidl-test/FooHelper.h>
+#include <hidl-test/PointerHelper.h>
+
 #include <hidl/IServiceManager.h>
 #include <hidl/Status.h>
 #include <hwbinder/IPCThreadState.h>
@@ -38,12 +41,6 @@
 // TODO uncomment this when kernel is patched with pointer changes.
 //#define HIDL_RUN_POINTER_TESTS 1
 
-// Defined in FooCallback.
-static const nsecs_t DELAY_S = 1;
-static const nsecs_t DELAY_NS = seconds_to_nanoseconds(DELAY_S);
-static const nsecs_t TOLERANCE_NS = milliseconds_to_nanoseconds(10);
-static const nsecs_t ONEWAY_TOLERANCE_NS = milliseconds_to_nanoseconds(1);
-
 // forward declarations.
 class PassthroughEnvironment;
 class BinderizedEnvironment;
@@ -75,8 +72,15 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::hidl_string;
 using ::android::sp;
+using ::android::to_string;
 using ::android::Mutex;
+using ::android::MultiDimensionalToString;
 using ::android::Condition;
+using ::android::DELAY_S;
+using ::android::DELAY_NS;
+using ::android::TOLERANCE_NS;
+using ::android::ONEWAY_TOLERANCE_NS;
+using std::to_string;
 
 template <typename T>
 static inline ::testing::AssertionResult isOk(::android::hardware::Return<T> ret) {
@@ -93,43 +97,6 @@
     return true;
 }
 
-// NOTE: duplicated code in Graph.cpp
-static void simpleGraph(IGraph::Graph& g) {
-    g.nodes.resize(2);
-    g.edges.resize(1);
-    g.nodes[0].data = 10;
-    g.nodes[1].data = 20;
-    g.edges[0].left = &g.nodes[0];
-    g.edges[0].right = &g.nodes[1];
-}
-
-static bool isSimpleGraph(const IGraph::Graph &g) {
-    if(g.nodes.size() != 2) return false;
-    if(g.edges.size() != 1) return false;
-    if(g.nodes[0].data != 10) return false;
-    if(g.nodes[1].data != 20) return false;
-    if(g.edges[0].left != &g.nodes[0]) return false;
-    if(g.edges[0].right != &g.nodes[1]) return false;
-    return true;
-}
-
-static void logSimpleGraph(const char *prefix, const IGraph::Graph& g) {
-    ALOGI("%s Graph %p, %d nodes, %d edges", prefix, &g, (int)g.nodes.size(), (int)g.edges.size());
-    std::ostringstream os;
-    for(size_t i = 0; i < g.nodes.size(); i++)
-      os << &g.nodes[i] << " = " << g.nodes[i].data << ", ";
-    ALOGI("%s Nodes: [%s]", prefix, os.str().c_str());
-    os.str("");
-    os.clear();
-    for(size_t i = 0; i < g.edges.size(); i++)
-      os << g.edges[i].left << " -> " << g.edges[i].right << ", ";
-    ALOGI("%s Edges: [%s]", prefix, os.str().c_str());
-}
-// end duplicated code
-
-// NOTE: duplicated code in Foo.cpp
-using std::to_string;
-
 struct Simple : public ISimple {
     Simple(int32_t cookie)
         : mCookie(cookie) {
@@ -142,115 +109,6 @@
 private:
     int32_t mCookie;
 };
-
-static std::string to_string(const IFoo::StringMatrix5x3 &M);
-static std::string to_string(const IFoo::StringMatrix3x5 &M);
-static std::string to_string(const hidl_string &s);
-
-template<typename T>
-static std::string to_string(const T *elems, size_t n) {
-    std::string out;
-    out = "[";
-    for (size_t i = 0; i < n; ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-        out += to_string(elems[i]);
-    }
-    out += "]";
-
-    return out;
-}
-
-template<typename T, size_t SIZE>
-static std::string to_string(const hidl_array<T, SIZE> &array) {
-    return to_string(&array[0], SIZE);
-}
-
-template<typename T, size_t SIZE1, size_t SIZE2>
-static std::string to_string(const hidl_array<T, SIZE1, SIZE2> &array) {
-    std::string out;
-    out = "[";
-    for (size_t i = 0; i < SIZE1; ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-
-        out += "[";
-        for (size_t j = 0; j < SIZE2; ++j) {
-            if (j > 0) {
-                out += ", ";
-            }
-
-            out += to_string(array[i][j]);
-        }
-        out += "]";
-    }
-    out += "]";
-
-    return out;
-}
-
-template<typename T>
-static std::string to_string(const hidl_vec<T> &vec) {
-    return to_string(&vec[0], vec.size());
-}
-
-static std::string to_string(const IFoo::StringMatrix5x3 &M) {
-    return to_string(M.s);
-}
-
-static std::string to_string(const IFoo::StringMatrix3x5 &M) {
-    return to_string(M.s);
-}
-
-static std::string to_string(const hidl_string &s) {
-    return std::string("'") + s.c_str() + "'";
-}
-
-static std::string QuuxToString(const IFoo::Quux &val) {
-    std::string s;
-
-    s = "Quux(first='";
-    s += val.first.c_str();
-    s += "', last='";
-    s += val.last.c_str();
-    s += "')";
-
-    return s;
-}
-
-static std::string MultiDimensionalToString(const IFoo::MultiDimensional &val) {
-    std::string s;
-
-    s += "MultiDimensional(";
-
-    s += "quuxMatrix=[";
-
-    size_t k = 0;
-    for (size_t i = 0; i < 5; ++i) {
-        if (i > 0) {
-            s += ", ";
-        }
-
-        s += "[";
-        for (size_t j = 0; j < 3; ++j, ++k) {
-            if (j > 0) {
-                s += ", ";
-            }
-
-            s += QuuxToString(val.quuxMatrix[i][j]);
-        }
-    }
-    s += "]";
-
-    s += ")";
-
-    return s;
-}
-
-// end duplicated code
-
 void signal_handler(int signal)
 {
     if (signal == SIGTERM) {
@@ -841,16 +699,16 @@
 
 TEST_F(HidlTest, PassAGraphTest) {
     IGraph::Graph g;
-    simpleGraph(g);
-    logSimpleGraph("CLIENT", g);
+    ::android::simpleGraph(g);
+    ::android::logSimpleGraph("CLIENT", g);
     ALOGI("CLIENT call passAGraph");
     EXPECT_OK(graphInterface->passAGraph(g));
 }
 
 TEST_F(HidlTest, GiveAGraphTest) {
     EXPECT_OK(graphInterface->giveAGraph([&](const auto &newGraph) {
-        logSimpleGraph("CLIENT", newGraph);
-        EXPECT_TRUE(isSimpleGraph(newGraph));
+        ::android::logSimpleGraph("CLIENT", newGraph);
+        EXPECT_TRUE(::android::isSimpleGraph(newGraph));
     }));
 }
 TEST_F(HidlTest, PassANodeTest) {
@@ -859,7 +717,7 @@
 }
 TEST_F(HidlTest, PassTwoGraphsTest) {
     IGraph::Graph g;
-    simpleGraph(g);
+    ::android::simpleGraph(g);
     EXPECT_OK(graphInterface->passTwoGraphs(&g, &g));
 }
 TEST_F(HidlTest, PassAGammaTest) {
diff --git a/utils/Formatter.cpp b/utils/Formatter.cpp
index fc4dd73..4aab8a5 100644
--- a/utils/Formatter.cpp
+++ b/utils/Formatter.cpp
@@ -33,13 +33,23 @@
     mFile = NULL;
 }
 
-void Formatter::indent() {
-    ++mIndentDepth;
+void Formatter::indent(size_t level) {
+    mIndentDepth += level;
 }
 
-void Formatter::unindent() {
-    assert(mIndentDepth > 0);
-    --mIndentDepth;
+void Formatter::unindent(size_t level) {
+    assert(mIndentDepth >= level);
+    mIndentDepth -= level;
+}
+
+void Formatter::indentBlock(size_t level, std::function<void(void)> func) {
+    this->indent(level);
+    func();
+    this->unindent(level);
+}
+
+void Formatter::indentBlock(std::function<void(void)> func) {
+    this->indentBlock(1, func);
 }
 
 void Formatter::setLinePrefix(const std::string &prefix) {
diff --git a/utils/include/hidl-util/Formatter.h b/utils/include/hidl-util/Formatter.h
index 787877f..1e7e03b 100644
--- a/utils/include/hidl-util/Formatter.h
+++ b/utils/include/hidl-util/Formatter.h
@@ -19,6 +19,7 @@
 #define FORMATTER_H_
 
 #include <android-base/macros.h>
+#include <functional>
 #include <string>
 
 namespace android {
@@ -28,8 +29,17 @@
     Formatter(FILE *file = NULL);
     ~Formatter();
 
-    void indent();
-    void unindent();
+    void indent(size_t level = 1);
+    void unindent(size_t level = 1);
+
+    // out.indentBlock(2, [&] {
+    //     out << "Meow\n";
+    // });
+    void indentBlock(size_t level, std::function<void(void)> func);
+    // out.indentBlock([&] {
+    //     out << "Meow\n";
+    // });
+    void indentBlock(std::function<void(void)> func);
 
     Formatter &operator<<(const std::string &out);
     Formatter &operator<<(size_t n);