Dump client PIDs for passthrough HALs.

* This is done with registerPassthroughClient in IServiceManager; when a
  service is retrieved through the passthrough service manager, its PID
  will be recoreded by the binderized service manager.
* The action of dumping all available dynamic libraries is now done by
  dumpAllLibraries.
Bug: 34712252
Test: lshal

Change-Id: I7f08e3255ffed0f46435843504e0e225d0d9bbc9
diff --git a/cmds/lshal/lshal.cpp b/cmds/lshal/lshal.cpp
index 07cd9f4..9998a46 100644
--- a/cmds/lshal/lshal.cpp
+++ b/cmds/lshal/lshal.cpp
@@ -28,7 +28,9 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
 
+using ::android::sp;
 using ::android::hardware::hidl_string;
+using ::android::hidl::manager::V1_0::IServiceManager;
 
 template <typename A, typename B, typename C, typename D, typename E, typename F>
 void printColumn(std::stringstream &stream,
@@ -45,6 +47,21 @@
            << endl;
 }
 
+template <typename A>
+std::string join(const A &components, const std::string &separator) {
+    std::stringstream out;
+    bool first = true;
+    for (const auto &component : components) {
+        if (!first) {
+            out << separator;
+        }
+        out << component;
+
+        first = false;
+    }
+    return out.str();
+}
+
 std::string toHexString(uint64_t t) {
     std::ostringstream os;
     os << std::hex << std::setfill('0') << std::setw(16) << t;
@@ -92,6 +109,56 @@
     return true;
 }
 
+void dumpAllLibraries(std::stringstream &stream, const std::string &mode,
+            const sp<IServiceManager> &manager) {
+    using namespace ::std;
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = manager->list([&] (const auto &fqInstanceNames) {
+        for (const auto &fqInstanceName : fqInstanceNames) {
+            const auto pair = split(fqInstanceName, '/');
+            const auto &serviceName = pair.first;
+            const auto &instanceName = pair.second;
+            printColumn(stream,
+                serviceName,
+                instanceName,
+                mode,
+                "N/A",
+                "N/A",
+                "N/A");
+        }
+    });
+    if (!ret.isOk()) {
+        cerr << "Error: Failed to call debugDump on defaultServiceManager(): "
+             << ret.description() << endl;
+    }
+}
+
+void dumpPassthrough(std::stringstream &stream, const std::string &mode,
+            const sp<IServiceManager> &manager) {
+    using namespace ::std;
+    using namespace ::android::hardware;
+    using namespace ::android::hidl::manager::V1_0;
+    using namespace ::android::hidl::base::V1_0;
+    auto ret = manager->debugDump([&] (const auto &infos) {
+        for (const auto &info : infos) {
+
+            printColumn(stream,
+                info.interfaceName,
+                info.instanceName,
+                mode,
+                info.clientPids.size() == 1 ? std::to_string(info.clientPids[0]) : "N/A",
+                "N/A",
+                join(info.clientPids, " "));
+        }
+    });
+    if (!ret.isOk()) {
+        cerr << "Error: Failed to call debugDump on defaultServiceManager(): "
+             << ret.description() << endl;
+    }
+}
+
 void dumpBinderized(std::stringstream &stream, const std::string &mode,
             const sp<IServiceManager> &manager) {
     using namespace ::std;
@@ -187,6 +254,15 @@
         cerr << "Failed to get defaultServiceManager()!" << endl;
     } else {
         dumpBinderized(stream, "hwbinder", bManager);
+        // Passthrough PIDs are registered to the binderized manager as well.
+        dumpPassthrough(stream, "passthrough", bManager);
+    }
+
+    auto pManager = getPassthroughServiceManager();
+    if (pManager == nullptr) {
+        cerr << "Failed to get getPassthroughServiceManager()!" << endl;
+    } else {
+        dumpAllLibraries(stream, "passthrough", pManager);
     }
 
     cout << stream.rdbuf();