From f4bee849129bd1b1e557c4e3cb1a4e5ef501d71d Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 1 Feb 2017 15:54:01 -0800 Subject: lshal: print pids of client processes. Bug: 34777099 Bug: 34861460 Test: lshal Test: NFC / light / audio with and without persistent.hal.binderized; run lshal to reflect this. Change-Id: I50aa5d99fb14957b1e40a405836e68c235a22006 --- cmds/lshal/Android.bp | 1 + cmds/lshal/lshal.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 4 deletions(-) (limited to 'cmds') diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp index dd8104d180..c3805985c4 100644 --- a/cmds/lshal/Android.bp +++ b/cmds/lshal/Android.bp @@ -15,6 +15,7 @@ cc_binary { name: "lshal", shared_libs: [ + "libbase", "libutils", "libhidlbase", "android.hidl.manager@1.0", diff --git a/cmds/lshal/lshal.cpp b/cmds/lshal/lshal.cpp index 19374750d6..bc5eaf24c5 100644 --- a/cmds/lshal/lshal.cpp +++ b/cmds/lshal/lshal.cpp @@ -18,25 +18,69 @@ #include #include +#include #include #include #include +#include +#include #include #include -template +template void printColumn(std::stringstream &stream, - const A &a, const B &b, const C &c, const D &d) { + const A &a, const B &b, const C &c, const D &d, const E &e) { using namespace ::std; stream << left << setw(70) << a << "\t" << setw(20) << b << "\t" << setw(10) << c << "\t" << setw(5) << d << "\t" + << setw(0) << e << endl; } +std::string toHexString(uint64_t t) { + std::ostringstream os; + os << std::hex << std::setfill('0') << std::setw(16) << t; + return os.str(); +} + +::android::status_t getReferencedPids( + pid_t serverPid, std::map *objects) { + + std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid)); + if (!ifs.is_open()) { + return ::android::PERMISSION_DENIED; + } + + static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); + + std::string line; + std::smatch match; + while(getline(ifs, line)) { + if (!std::regex_search(line, match, prefix)) { + // the line doesn't start with the correct prefix + continue; + } + std::string ptrString = "0x" + match.str(2); // use number after c + uint64_t ptr; + if (!::android::base::ParseUint(ptrString.c_str(), &ptr)) { + // Should not reach here, but just be tolerant. + std::cerr << "Could not parse number " << ptrString << std::endl; + continue; + } + const std::string proc = " proc "; + auto pos = line.rfind(proc); + if (pos != std::string::npos) { + (*objects)[ptr] += line.substr(pos + proc.size()); + } + } + return ::android::OK; +} + + int dump() { using namespace ::std; using namespace ::android::hardware; @@ -51,7 +95,7 @@ int dump() { stream << "All services:" << endl; stream << left; - printColumn(stream, "Interface", "Instance", "Transport", "Ref"); + printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients"); for (const auto &pair : mapping) { const std::string &mode = pair.first; @@ -63,12 +107,29 @@ int dump() { } auto ret = manager->debugDump([&](const auto ®istered) { + // server pid, .ptr value of binder object, child pids + std::map> allPids; + for (const auto &info : registered) { + if (info.pid < 0) { + continue; + } + pid_t serverPid = info.pid; + allPids[serverPid].clear(); + } + for (auto &pair : allPids) { + pid_t serverPid = pair.first; + if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) { + std::cerr << "Warning: no information for PID " << serverPid + << ", are you root?" << std::endl; + } + } for (const auto &info : registered) { printColumn(stream, info.interfaceName, info.instanceName.empty() ? "N/A" : info.instanceName, mode, - info.refCount < 0 ? "N/A" : std::to_string(info.refCount)); + info.pid < 0 ? "N/A" : std::to_string(info.pid), + info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]); } }); if (!ret.isOk()) { -- cgit v1.2.3-59-g8ed1b