Merge changes Id98050c5,Ib60bb047 am: 08d36d87bc
am: 00dfa0005f

Change-Id: I1fa1e69f8e11fef194aef647742ae62b8c21e688
diff --git a/AST.h b/AST.h
index 9472582..a55cd8c 100644
--- a/AST.h
+++ b/AST.h
@@ -333,8 +333,6 @@
                               const NamedReference<Type>* arg, bool isReader,
                               bool addPrefixToName) const;
 
-    void emitTypeDeclarations(Formatter& out) const;
-    void emitJavaTypeDeclarations(Formatter& out) const;
     void emitVtsTypeDeclarations(Formatter& out) const;
 
     DISALLOW_COPY_AND_ASSIGN(AST);
diff --git a/DocComment.cpp b/DocComment.cpp
index 91bc676..eba3fc0 100644
--- a/DocComment.cpp
+++ b/DocComment.cpp
@@ -16,16 +16,18 @@
 
 #include "DocComment.h"
 
+#include <android-base/strings.h>
 #include <hidl-util/StringHelper.h>
 
 #include <cctype>
 #include <sstream>
 
+#include <iostream>
+
 namespace android {
 
 DocComment::DocComment(const std::string& comment) {
-    std::vector<std::string> lines;
-    StringHelper::SplitString(comment, '\n', &lines);
+    std::vector<std::string> lines = base::Split(base::Trim(comment), "\n");
 
     bool foundFirstLine = false;
 
@@ -40,17 +42,12 @@
         if (idx < line.size() && line[idx] == '*') idx++;
         if (idx < line.size() && line[idx] == ' ') idx++;
 
-        if (idx < line.size()) {
-            foundFirstLine = true;
-        }
+        bool isEmptyLine = idx == line.size();
 
+        foundFirstLine = foundFirstLine || !isEmptyLine;
         if (!foundFirstLine) continue;
 
-        is << line.substr(idx);
-
-        if (l + 1 < lines.size()) {
-            is << "\n";
-        }
+        is << line.substr(idx) << "\n";
     }
 
     mComment = is.str();
diff --git a/DocComment.h b/DocComment.h
index e0677eb..b397326 100644
--- a/DocComment.h
+++ b/DocComment.h
@@ -43,7 +43,10 @@
         }
     }
 
-   private:
+  protected:
+    const DocComment* getDocComment() const { return mDocComment; }
+
+  private:
     const DocComment* mDocComment = nullptr;
 };
 
diff --git a/Method.cpp b/Method.cpp
index d81af7c..482bae5 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -149,8 +149,10 @@
     return mJavaImpl.find(type) != mJavaImpl.end();
 }
 
-Method *Method::copySignature() const {
-    return new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, Location());
+Method* Method::copySignature() const {
+    Method* method = new Method(mName.c_str(), mArgs, mResults, mOneway, mAnnotations, location());
+    method->setDocComment(getDocComment());
+    return method;
 }
 
 void Method::setSerialId(size_t serial) {
diff --git a/generateCpp.cpp b/generateCpp.cpp
index affc53d..99ef80a 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -103,17 +103,43 @@
 static void declareGetService(Formatter &out, const std::string &interfaceName, bool isTry) {
     const std::string functionName = isTry ? "tryGetService" : "getService";
 
+    if (isTry) {
+        DocComment(
+                "This gets the service of this type with the specified instance name. If the\n"
+                "service is currently not available or not in the VINTF manifest on a Trebilized\n"
+                "device, this will return nullptr. This is useful when you don't want to block\n"
+                "during device boot. If getStub is true, this will try to return an unwrapped\n"
+                "passthrough implementation in the same process. This is useful when getting an\n"
+                "implementation from the same partition/compilation group.\n\n"
+                "In general, prefer getService(std::string,bool)")
+                .emit(out);
+    } else {
+        DocComment(
+                "This gets the service of this type with the specified instance name. If the\n"
+                "service is not in the VINTF manifest on a Trebilized device, this will return\n"
+                "nullptr. If the service is not available, this will wait for the service to\n"
+                "become available. If the service is a lazy service, this will start the service\n"
+                "and return when it becomes available. If getStub is true, this will try to\n"
+                "return an unwrapped passthrough implementation in the same process. This is\n"
+                "useful when getting an implementation from the same partition/compilation group.")
+                .emit(out);
+    }
     out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
         << "const std::string &serviceName=\"default\", bool getStub=false);\n";
+    DocComment("Deprecated. See " + functionName + "(std::string, bool)").emit(out);
     out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
         << "const char serviceName[], bool getStub=false)"
         << "  { std::string str(serviceName ? serviceName : \"\");"
         << "      return " << functionName << "(str, getStub); }\n";
+    DocComment("Deprecated. See " + functionName + "(std::string, bool)").emit(out);
     out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
         << "const ::android::hardware::hidl_string& serviceName, bool getStub=false)"
         // without c_str the std::string constructor is ambiguous
         << "  { std::string str(serviceName.c_str());"
         << "      return " << functionName << "(str, getStub); }\n";
+    DocComment("Calls " + functionName +
+               "(\"default\", bool). This is the recommended instance name for singleton services.")
+            .emit(out);
     out << "static ::android::sp<" << interfaceName << "> " << functionName << "("
         << "bool getStub) { return " << functionName << "(\"default\", getStub); }\n";
 }
@@ -122,8 +148,13 @@
     declareGetService(out, interfaceName, true /* isTry */);
     declareGetService(out, interfaceName, false /* isTry */);
 
+    DocComment(
+            "Registers a service with the service manager. For Trebilized devices, the service\n"
+            "must also be in the VINTF manifest.")
+            .emit(out);
     out << "__attribute__ ((warn_unused_result))"
         << "::android::status_t registerAsService(const std::string &serviceName=\"default\");\n";
+    DocComment("Registers for notifications for when a service is registered.").emit(out);
     out << "static bool registerForNotifications(\n";
     out.indent(2, [&] {
         out << "const std::string &serviceName,\n"
@@ -228,6 +259,8 @@
     out << "\n";
 
     if (iface) {
+        iface->emitDocComment(out);
+
         out << "struct "
             << ifaceName;
 
@@ -244,17 +277,28 @@
 
         out.indent();
 
+        DocComment("Type tag for use in template logic that indicates this is a 'pure' class.")
+                .emit(out);
         generateCppTag(out, "android::hardware::details::i_tag");
+
+        DocComment("Fully qualified interface name: \"" + iface->fqName().string() + "\"")
+                .emit(out);
+        out << "static const char* descriptor;\n\n";
+
+        iface->emitTypeDeclarations(out);
+    } else {
+        mRootScope.emitTypeDeclarations(out);
     }
 
-    emitTypeDeclarations(out);
-
     if (iface) {
+        DocComment(
+                "Returns whether this object's implementation is outside of the current process.")
+                .emit(out);
         out << "virtual bool isRemote() const ";
         if (!isIBase()) {
             out << "override ";
         }
-        out << "{ return false; }\n\n";
+        out << "{ return false; }\n";
 
         for (const auto& tuple : iface->allMethodsFromRoot()) {
             const Method* method = tuple.method();
@@ -265,6 +309,7 @@
             const NamedReference<Type>* elidedReturn = method->canElideCallback();
 
             if (elidedReturn == nullptr && returnsValue) {
+                DocComment("Return callback for " + method->name()).emit(out);
                 out << "using "
                     << method->name()
                     << "_cb = std::function<void(";
@@ -297,10 +342,14 @@
             out << ";\n";
         }
 
-        out << "// cast static functions\n";
+        out << "\n// cast static functions\n";
         std::string childTypeResult = iface->getCppResultType();
 
         for (const Interface *superType : iface->typeChain()) {
+            DocComment(
+                    "This performs a checked cast based on what the underlying implementation "
+                    "actually is.")
+                    .emit(out);
             out << "static ::android::hardware::Return<"
                 << childTypeResult
                 << "> castFrom("
@@ -309,11 +358,10 @@
                 << ", bool emitError = false);\n";
         }
 
-        out << "\nstatic const char* descriptor;\n\n";
-
         if (isIBase()) {
-            out << "// skipped getService, registerAsService, registerForNotifications\n\n";
+            out << "\n// skipped getService, registerAsService, registerForNotifications\n\n";
         } else {
+            out << "\n// helper methods for interactions with the hwservicemanager\n";
             declareServiceManagerInteractions(out, iface->localName());
         }
     }
@@ -384,10 +432,6 @@
     out << "\n#endif  // " << guard << "\n";
 }
 
-void AST::emitTypeDeclarations(Formatter& out) const {
-    return mRootScope.emitTypeDeclarations(out);
-}
-
 static std::string wrapPassthroughArg(Formatter& out, const NamedReference<Type>* arg,
                                       std::string name, std::function<void(void)> handleError) {
     if (!arg->type().isInterface()) {
@@ -588,6 +632,7 @@
 }
 
 void AST::generateTemplatizationLink(Formatter& out) const {
+    DocComment("The pure class is what this class wraps.").emit(out);
     out << "typedef " << mRootScope.getInterface()->localName() << " Pure;\n\n";
 }
 
@@ -648,6 +693,8 @@
 
     out.endl();
     generateTemplatizationLink(out);
+    DocComment("Type tag for use in template logic that indicates this is a 'native' class.")
+            .emit(out);
     generateCppTag(out, "android::hardware::details::bnhw_tag");
 
     out << "::android::sp<" << iface->localName() << "> getImpl() { return _hidl_mImpl; }\n";
@@ -740,6 +787,8 @@
         << "\n\n";
 
     generateTemplatizationLink(out);
+    DocComment("Type tag for use in template logic that indicates this is a 'proxy' class.")
+            .emit(out);
     generateCppTag(out, "android::hardware::details::bphw_tag");
 
     out << "virtual bool isRemote() const override { return true; }\n\n";
diff --git a/generateJava.cpp b/generateJava.cpp
index 33bd289..b746cc3 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -71,6 +71,19 @@
         const std::string& ifaceName,
         const std::string& fqName,
         bool isRetry) {
+    if (isRetry) {
+        DocComment(
+                "This will invoke the equivalent of the C++ getService(std::string) if retry is\n"
+                "true or tryGetService(std::string) if retry is false. If the service is\n"
+                "available on the device and retry is true, this will wait for the service to\n"
+                "start. Otherwise, it will return immediately even if the service is null.")
+                .emit(out);
+    } else {
+        DocComment(
+                "Warning: this will not wait for the interface to come up if it hasn't yet\n"
+                "started. See getService(String,boolean) instead.")
+                .emit(out);
+    }
     out << "public static "
         << ifaceName
         << " getService(String serviceName";
@@ -90,6 +103,14 @@
         out << "));\n";
     }).endl().endl();
 
+    if (isRetry) {
+        DocComment("Calls getService(\"default\",retry).").emit(out);
+    } else {
+        DocComment(
+                "Warning: this will not wait for the interface to come up if it hasn't yet "
+                "started. See getService(String,boolean) instead.")
+                .emit(out);
+    }
     out << "public static "
         << ifaceName
         << " getService(";
@@ -128,6 +149,8 @@
 
     const Interface *superType = iface->superType();
 
+    iface->emitDocComment(out);
+
     out << "public interface " << ifaceName << " extends ";
 
     if (superType != nullptr) {
@@ -139,12 +162,14 @@
     out << " {\n";
     out.indent();
 
+    DocComment("Fully-qualified interface name for this interface.").emit(out);
     out << "public static final String kInterfaceName = \""
         << mPackage.string()
         << "::"
         << ifaceName
         << "\";\n\n";
 
+    DocComment("Does a checked conversion from a binder to this class.").emit(out);
     out << "/* package private */ static "
         << ifaceName
         << " asInterface(android.os.IHwBinder binder) {\n";
@@ -196,6 +221,7 @@
     out.unindent();
     out << "}\n\n";
 
+    DocComment("Does a checked conversion from any interface to this class.").emit(out);
     out << "public static "
         << ifaceName
         << " castFrom(android.os.IHwInterface iface) {\n";
@@ -213,7 +239,7 @@
     emitGetService(out, ifaceName, iface->fqName().string(), true /* isRetry */);
     emitGetService(out, ifaceName, iface->fqName().string(), false /* isRetry */);
 
-    emitJavaTypeDeclarations(out);
+    iface->emitJavaTypeDeclarations(out, false /* atTopLevel */);
 
     for (const auto &method : iface->methods()) {
         const bool returnsValue = !method->results().empty();
@@ -646,8 +672,4 @@
     out << "}\n";
 }
 
-void AST::emitJavaTypeDeclarations(Formatter& out) const {
-    mRootScope.emitJavaTypeDeclarations(out, false /* atTopLevel */);
-}
-
 }  // namespace android