Loading cmds/lshal/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ cc_library_static { name: "liblshal", shared_libs: [ "libbase", "libbinderdebug", "libcutils", "libutils", "libhidlbase", Loading Loading @@ -47,6 +48,7 @@ cc_defaults { name: "lshal_defaults", shared_libs: [ "libbase", "libbinderdebug", "libcutils", "libutils", "libhidlbase", Loading cmds/lshal/ListCommand.cpp +6 −90 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <hidl-hash/Hash.h> #include <hidl-util/FQName.h> Loading Loading @@ -203,97 +202,14 @@ VintfInfo ListCommand::getVintfInfo(const std::string& fqInstanceName, lshal::getVintfInfo(getFrameworkMatrix(), fqInstance, ta, FRAMEWORK_MATRIX); } static bool scanBinderContext(pid_t pid, const std::string &contextName, std::function<void(const std::string&)> eachLine) { std::ifstream ifs("/dev/binderfs/binder_logs/proc/" + std::to_string(pid)); if (!ifs.is_open()) { ifs.open("/d/binder/proc/" + std::to_string(pid)); if (!ifs.is_open()) { return false; } } static const std::regex kContextLine("^context (\\w+)$"); bool isDesiredContext = false; std::string line; std::smatch match; while(getline(ifs, line)) { if (std::regex_search(line, match, kContextLine)) { isDesiredContext = match.str(1) == contextName; continue; } if (!isDesiredContext) { continue; } eachLine(line); } return true; } bool ListCommand::getPidInfo( pid_t serverPid, PidInfo *pidInfo) const { static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)"); std::smatch match; return scanBinderContext(serverPid, "hwbinder", [&](const std::string& line) { if (std::regex_search(line, match, kReferencePrefix)) { const 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. err() << "Could not parse number " << ptrString << std::endl; return; } const std::string proc = " proc "; auto pos = line.rfind(proc); if (pos != std::string::npos) { for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) { int32_t pid; if (!::android::base::ParseInt(pidStr, &pid)) { err() << "Could not parse number " << pidStr << std::endl; return; } pidInfo->refPids[ptr].push_back(pid); } } return; } if (std::regex_search(line, match, kThreadPrefix)) { // "1" is waiting in binder driver // "2" is poll. It's impossible to tell if these are in use. // and HIDL default code doesn't use it. bool isInUse = match.str(1) != "1"; // "0" is a thread that has called into binder // "1" is looper thread // "2" is main looper thread bool isHwbinderThread = match.str(2) != "0"; if (!isHwbinderThread) { return; } if (isInUse) { pidInfo->threadUsage++; } pidInfo->threadCount++; return; } // not reference or thread line return; }); pid_t serverPid, BinderPidInfo *pidInfo) const { const auto& status = getBinderPidInfo(BinderDebugContext::HWBINDER, serverPid, pidInfo); return status == OK; } const PidInfo* ListCommand::getPidInfoCached(pid_t serverPid) { auto pair = mCachedPidInfos.insert({serverPid, PidInfo{}}); const BinderPidInfo* ListCommand::getPidInfoCached(pid_t serverPid) { auto pair = mCachedPidInfos.insert({serverPid, BinderPidInfo{}}); if (pair.second /* did insertion take place? */) { if (!getPidInfo(serverPid, &pair.first->second)) { return nullptr; Loading Loading @@ -727,7 +643,7 @@ Status ListCommand::fetchBinderizedEntry(const sp<IServiceManager> &manager, entry->arch = fromBaseArchitecture(debugInfo.arch); if (debugInfo.pid != NO_PID) { const PidInfo* pidInfo = getPidInfoCached(debugInfo.pid); const BinderPidInfo* pidInfo = getPidInfoCached(debugInfo.pid); if (pidInfo == nullptr) { handleError(IO_ERROR, "no information for PID " + std::to_string(debugInfo.pid) + Loading cmds/lshal/ListCommand.h +4 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <android-base/macros.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <binderdebug/BinderDebug.h> #include <hidl-util/FqInstance.h> #include <vintf/HalManifest.h> #include <vintf/VintfObject.h> Loading @@ -40,12 +41,6 @@ namespace lshal { class Lshal; struct PidInfo { std::map<uint64_t, Pids> refPids; // pids that are referenced uint32_t threadUsage; // number of threads in use uint32_t threadCount; // number of threads total }; enum class HalType { BINDERIZED_SERVICES = 0, PASSTHROUGH_CLIENTS, Loading Loading @@ -110,9 +105,9 @@ protected: // Get relevant information for a PID by parsing files under // /dev/binderfs/binder_logs or /d/binder. // It is a virtual member function so that it can be mocked. virtual bool getPidInfo(pid_t serverPid, PidInfo *info) const; virtual bool getPidInfo(pid_t serverPid, BinderPidInfo *info) const; // Retrieve from mCachedPidInfos and call getPidInfo if necessary. const PidInfo* getPidInfoCached(pid_t serverPid); const BinderPidInfo* getPidInfoCached(pid_t serverPid); void dumpTable(const NullableOStream<std::ostream>& out) const; void dumpVintf(const NullableOStream<std::ostream>& out) const; Loading Loading @@ -191,7 +186,7 @@ protected: std::map<pid_t, std::string> mCmdlines; // Cache for getPidInfo. std::map<pid_t, PidInfo> mCachedPidInfos; std::map<pid_t, BinderPidInfo> mCachedPidInfos; // Cache for getPartition. std::map<pid_t, Partition> mPartitions; Loading cmds/lshal/TableEntry.h +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ namespace android { namespace lshal { using android::procpartition::Partition; using Pids = std::vector<int32_t>; using Pids = std::vector<pid_t>; enum class TableColumnType : unsigned int { INTERFACE_NAME = 0, Loading cmds/lshal/test.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -233,12 +233,12 @@ public: return ListCommand::dumpVintf(out); } void internalPostprocess() { ListCommand::postprocess(); } const PidInfo* getPidInfoCached(pid_t serverPid) { const BinderPidInfo* getPidInfoCached(pid_t serverPid) { return ListCommand::getPidInfoCached(serverPid); } MOCK_METHOD0(postprocess, void()); MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, PidInfo*)); MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, BinderPidInfo*)); MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t)); MOCK_METHOD1(getPartition, Partition(pid_t)); Loading Loading @@ -299,8 +299,8 @@ static uint64_t getPtr(pid_t serverId) { return 10000 + serverId; } static std::vector<pid_t> getClients(pid_t serverId) { return {serverId + 1, serverId + 3}; } static PidInfo getPidInfoFromId(pid_t serverId) { PidInfo info; static BinderPidInfo getPidInfoFromId(pid_t serverId) { BinderPidInfo info; info.refPids[getPtr(serverId)] = getClients(serverId); info.threadUsage = 10 + serverId; info.threadCount = 20 + serverId; Loading Loading @@ -363,7 +363,7 @@ public: void initMockList() { mockList = std::make_unique<NiceMock<MockListCommand>>(lshal.get()); ON_CALL(*mockList, getPidInfo(_,_)).WillByDefault(Invoke( [](pid_t serverPid, PidInfo* info) { [](pid_t serverPid, BinderPidInfo* info) { *info = getPidInfoFromId(serverPid); return true; })); Loading Loading
cmds/lshal/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ cc_library_static { name: "liblshal", shared_libs: [ "libbase", "libbinderdebug", "libcutils", "libutils", "libhidlbase", Loading Loading @@ -47,6 +48,7 @@ cc_defaults { name: "lshal_defaults", shared_libs: [ "libbase", "libbinderdebug", "libcutils", "libutils", "libhidlbase", Loading
cmds/lshal/ListCommand.cpp +6 −90 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <hidl-hash/Hash.h> #include <hidl-util/FQName.h> Loading Loading @@ -203,97 +202,14 @@ VintfInfo ListCommand::getVintfInfo(const std::string& fqInstanceName, lshal::getVintfInfo(getFrameworkMatrix(), fqInstance, ta, FRAMEWORK_MATRIX); } static bool scanBinderContext(pid_t pid, const std::string &contextName, std::function<void(const std::string&)> eachLine) { std::ifstream ifs("/dev/binderfs/binder_logs/proc/" + std::to_string(pid)); if (!ifs.is_open()) { ifs.open("/d/binder/proc/" + std::to_string(pid)); if (!ifs.is_open()) { return false; } } static const std::regex kContextLine("^context (\\w+)$"); bool isDesiredContext = false; std::string line; std::smatch match; while(getline(ifs, line)) { if (std::regex_search(line, match, kContextLine)) { isDesiredContext = match.str(1) == contextName; continue; } if (!isDesiredContext) { continue; } eachLine(line); } return true; } bool ListCommand::getPidInfo( pid_t serverPid, PidInfo *pidInfo) const { static const std::regex kReferencePrefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+"); static const std::regex kThreadPrefix("^\\s*thread \\d+:\\s+l\\s+(\\d)(\\d)"); std::smatch match; return scanBinderContext(serverPid, "hwbinder", [&](const std::string& line) { if (std::regex_search(line, match, kReferencePrefix)) { const 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. err() << "Could not parse number " << ptrString << std::endl; return; } const std::string proc = " proc "; auto pos = line.rfind(proc); if (pos != std::string::npos) { for (const std::string &pidStr : split(line.substr(pos + proc.size()), ' ')) { int32_t pid; if (!::android::base::ParseInt(pidStr, &pid)) { err() << "Could not parse number " << pidStr << std::endl; return; } pidInfo->refPids[ptr].push_back(pid); } } return; } if (std::regex_search(line, match, kThreadPrefix)) { // "1" is waiting in binder driver // "2" is poll. It's impossible to tell if these are in use. // and HIDL default code doesn't use it. bool isInUse = match.str(1) != "1"; // "0" is a thread that has called into binder // "1" is looper thread // "2" is main looper thread bool isHwbinderThread = match.str(2) != "0"; if (!isHwbinderThread) { return; } if (isInUse) { pidInfo->threadUsage++; } pidInfo->threadCount++; return; } // not reference or thread line return; }); pid_t serverPid, BinderPidInfo *pidInfo) const { const auto& status = getBinderPidInfo(BinderDebugContext::HWBINDER, serverPid, pidInfo); return status == OK; } const PidInfo* ListCommand::getPidInfoCached(pid_t serverPid) { auto pair = mCachedPidInfos.insert({serverPid, PidInfo{}}); const BinderPidInfo* ListCommand::getPidInfoCached(pid_t serverPid) { auto pair = mCachedPidInfos.insert({serverPid, BinderPidInfo{}}); if (pair.second /* did insertion take place? */) { if (!getPidInfo(serverPid, &pair.first->second)) { return nullptr; Loading Loading @@ -727,7 +643,7 @@ Status ListCommand::fetchBinderizedEntry(const sp<IServiceManager> &manager, entry->arch = fromBaseArchitecture(debugInfo.arch); if (debugInfo.pid != NO_PID) { const PidInfo* pidInfo = getPidInfoCached(debugInfo.pid); const BinderPidInfo* pidInfo = getPidInfoCached(debugInfo.pid); if (pidInfo == nullptr) { handleError(IO_ERROR, "no information for PID " + std::to_string(debugInfo.pid) + Loading
cmds/lshal/ListCommand.h +4 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <android-base/macros.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <binderdebug/BinderDebug.h> #include <hidl-util/FqInstance.h> #include <vintf/HalManifest.h> #include <vintf/VintfObject.h> Loading @@ -40,12 +41,6 @@ namespace lshal { class Lshal; struct PidInfo { std::map<uint64_t, Pids> refPids; // pids that are referenced uint32_t threadUsage; // number of threads in use uint32_t threadCount; // number of threads total }; enum class HalType { BINDERIZED_SERVICES = 0, PASSTHROUGH_CLIENTS, Loading Loading @@ -110,9 +105,9 @@ protected: // Get relevant information for a PID by parsing files under // /dev/binderfs/binder_logs or /d/binder. // It is a virtual member function so that it can be mocked. virtual bool getPidInfo(pid_t serverPid, PidInfo *info) const; virtual bool getPidInfo(pid_t serverPid, BinderPidInfo *info) const; // Retrieve from mCachedPidInfos and call getPidInfo if necessary. const PidInfo* getPidInfoCached(pid_t serverPid); const BinderPidInfo* getPidInfoCached(pid_t serverPid); void dumpTable(const NullableOStream<std::ostream>& out) const; void dumpVintf(const NullableOStream<std::ostream>& out) const; Loading Loading @@ -191,7 +186,7 @@ protected: std::map<pid_t, std::string> mCmdlines; // Cache for getPidInfo. std::map<pid_t, PidInfo> mCachedPidInfos; std::map<pid_t, BinderPidInfo> mCachedPidInfos; // Cache for getPartition. std::map<pid_t, Partition> mPartitions; Loading
cmds/lshal/TableEntry.h +1 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ namespace android { namespace lshal { using android::procpartition::Partition; using Pids = std::vector<int32_t>; using Pids = std::vector<pid_t>; enum class TableColumnType : unsigned int { INTERFACE_NAME = 0, Loading
cmds/lshal/test.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -233,12 +233,12 @@ public: return ListCommand::dumpVintf(out); } void internalPostprocess() { ListCommand::postprocess(); } const PidInfo* getPidInfoCached(pid_t serverPid) { const BinderPidInfo* getPidInfoCached(pid_t serverPid) { return ListCommand::getPidInfoCached(serverPid); } MOCK_METHOD0(postprocess, void()); MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, PidInfo*)); MOCK_CONST_METHOD2(getPidInfo, bool(pid_t, BinderPidInfo*)); MOCK_CONST_METHOD1(parseCmdline, std::string(pid_t)); MOCK_METHOD1(getPartition, Partition(pid_t)); Loading Loading @@ -299,8 +299,8 @@ static uint64_t getPtr(pid_t serverId) { return 10000 + serverId; } static std::vector<pid_t> getClients(pid_t serverId) { return {serverId + 1, serverId + 3}; } static PidInfo getPidInfoFromId(pid_t serverId) { PidInfo info; static BinderPidInfo getPidInfoFromId(pid_t serverId) { BinderPidInfo info; info.refPids[getPtr(serverId)] = getClients(serverId); info.threadUsage = 10 + serverId; info.threadCount = 20 + serverId; Loading Loading @@ -363,7 +363,7 @@ public: void initMockList() { mockList = std::make_unique<NiceMock<MockListCommand>>(lshal.get()); ON_CALL(*mockList, getPidInfo(_,_)).WillByDefault(Invoke( [](pid_t serverPid, PidInfo* info) { [](pid_t serverPid, BinderPidInfo* info) { *info = getPidInfoFromId(serverPid); return true; })); Loading