Adds a debug(...) method to IBase, the base class for all Treble interfaces

The default implementation does nothing but this allows implementations to
emit diagnostics to a given file handle in a unified fashion.

Bug: 33961528
Test: hidl_test, hidl_test_java
Change-Id: Id7e8417275934c73032c9832c41e041d2d5d2fb7
diff --git a/Interface.cpp b/Interface.cpp
index e7ed545..174e544 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -53,6 +53,7 @@
     HIDL_UNLINK_TO_DEATH_TRANSACTION,
     HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION,
     HIDL_GET_REF_INFO_TRANSACTION,
+    HIDL_DEBUG_TRANSACTION,
     LAST_HIDL_TRANSACTION   = 0x00ffffff,
 };
 
@@ -301,6 +302,30 @@
     return true;
 }
 
+bool Interface::fillDebugMethod(Method *method) const {
+    if (method->name() != "debug") {
+        return false;
+    }
+
+    method->fillImplementation(
+        HIDL_DEBUG_TRANSACTION,
+        {
+            {IMPL_HEADER,
+                [this](auto &out) {
+                    out << "(void)fd;\n"
+                        << "(void)options;\n"
+                        << "return ::android::hardware::Void();";
+                }
+            },
+        }, /* cppImpl */
+        {
+            /* unused, as the debug method is hidden from Java */
+        } /* javaImpl */
+    );
+
+    return true;
+}
+
 static std::map<std::string, Method *> gAllReservedMethods;
 
 bool Interface::addMethod(Method *method) {
@@ -348,7 +373,9 @@
             || fillLinkToDeathMethod(method)
             || fillUnlinkToDeathMethod(method)
             || fillSetHALInstrumentationMethod(method)
-            || fillGetDebugInfoMethod(method);
+            || fillGetDebugInfoMethod(method)
+            || fillDebugMethod(method);
+
         if (!fillSuccess) {
             LOG(ERROR) << "ERROR: hidl-gen does not recognize a reserved method "
                        << method->name();
diff --git a/Interface.h b/Interface.h
index a063902..376a78c 100644
--- a/Interface.h
+++ b/Interface.h
@@ -121,6 +121,7 @@
     bool fillUnlinkToDeathMethod(Method *method) const;
     bool fillSetHALInstrumentationMethod(Method *method) const;
     bool fillGetDebugInfoMethod(Method *method) const;
+    bool fillDebugMethod(Method *method) const;
 
     DISALLOW_COPY_AND_ASSIGN(Interface);
 };
diff --git a/Method.cpp b/Method.cpp
index 476a10b..9d40856 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -89,6 +89,10 @@
     }
 }
 
+bool Method::isHiddenFromJava() const {
+    return isHidlReserved() && name() == "debug";
+}
+
 bool Method::overridesCppImpl(MethodImplType type) const {
     CHECK(mIsHidlReserved);
     return mCppImpl.find(type) != mCppImpl.end();
@@ -204,6 +208,10 @@
 }
 
 bool Method::isJavaCompatible() const {
+    if (isHiddenFromJava()) {
+        return true;
+    }
+
     for (const auto &arg : *mArgs) {
         if (!arg->isJavaCompatible()) {
             return false;
diff --git a/Method.h b/Method.h
index f9d7b8b..38f0dd2 100644
--- a/Method.h
+++ b/Method.h
@@ -61,6 +61,7 @@
     void cppImpl(MethodImplType type, Formatter &out) const;
     void javaImpl(MethodImplType type, Formatter &out) const;
     bool isHidlReserved() const { return mIsHidlReserved; }
+    bool isHiddenFromJava() const;
     const std::vector<Annotation *> &annotations() const;
 
     // Make a copy with the same name, args, results, oneway, annotations.
diff --git a/generateJava.cpp b/generateJava.cpp
index 317f88e..56ac2d6 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -236,6 +236,10 @@
     }
 
     for (const auto &method : iface->methods()) {
+        if (method->isHiddenFromJava()) {
+            continue;
+        }
+
         const bool returnsValue = !method->results().empty();
         const bool needsCallback = method->results().size() > 1;
 
@@ -302,6 +306,11 @@
     const Interface *prevInterface = nullptr;
     for (const auto &tuple : iface->allMethodsFromRoot()) {
         const Method *method = tuple.method();
+
+        if (method->isHiddenFromJava()) {
+            continue;
+        }
+
         const Interface *superInterface = tuple.interface();
         if (prevInterface != superInterface) {
             out << "// Methods from "
@@ -436,6 +445,10 @@
     out << "}\n\n";
 
     for (Method *method : iface->hidlReservedMethods()) {
+        if (method->isHiddenFromJava()) {
+            continue;
+        }
+
         // b/32383557 this is a hack. We need to change this if we have more reserved methods.
         CHECK_LE(method->results().size(), 1u);
         std::string resultType = method->results().size() == 0 ? "void" :
@@ -492,6 +505,7 @@
 
     for (const auto &tuple : iface->allMethodsFromRoot()) {
         const Method *method = tuple.method();
+
         const Interface *superInterface = tuple.interface();
         const bool returnsValue = !method->results().empty();
         const bool needsCallback = method->results().size() > 1;
@@ -503,6 +517,7 @@
             << " */:\n{\n";
 
         out.indent();
+
         if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) {
             method->javaImpl(IMPL_STUB, out);
             out.unindent();
@@ -515,6 +530,19 @@
             << superInterface->fullJavaName()
             << ".kInterfaceName);\n\n";
 
+        if (method->isHiddenFromJava()) {
+            // This is a method hidden from the Java side of things, it must not
+            // return any value and will simply signal success.
+            CHECK(!returnsValue);
+
+            out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n";
+            out << "_hidl_reply.send();\n";
+            out << "break;\n";
+            out.unindent();
+            out << "}\n\n";
+            continue;
+        }
+
         for (const auto &arg : method->args()) {
             emitJavaReaderWriter(
                     out,