Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ff0eeff authored by Devin Moore's avatar Devin Moore Committed by Gerrit Code Review
Browse files

Merge "Add libbinderdebug"

parents a21c6bc8 c03e3aa3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ cc_library_static {
    name: "liblshal",
    shared_libs: [
        "libbase",
        "libbinderdebug",
        "libcutils",
        "libutils",
        "libhidlbase",
@@ -47,6 +48,7 @@ cc_defaults {
    name: "lshal_defaults",
    shared_libs: [
        "libbase",
        "libbinderdebug",
        "libcutils",
        "libutils",
        "libhidlbase",
+6 −90
Original line number Diff line number Diff line
@@ -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>
@@ -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;
@@ -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) +
+4 −9
Original line number Diff line number Diff line
@@ -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>
@@ -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,
@@ -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;
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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,
+5 −5
Original line number Diff line number Diff line
@@ -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));

@@ -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;
@@ -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