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

Commit cd983732 authored by Yifan Hong's avatar Yifan Hong Committed by android-build-merger
Browse files

Merge changes from topic 'lshal' am: c9bc0372 am: d99d31d5

am: 5581e229

Change-Id: I526b604879c5c5103a7d0f9a66471534383c6175
parents cc070b4d 5581e229
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ class HardwareServiceManagerMock : public HServiceManager {
                const hidl_string&,
                const sp<IServiceNotification>&));
    MOCK_METHOD1(debugDump, R<void>(debugDump_cb));
    MOCK_METHOD3(registerPassthroughClient, R<void>(
        const hidl_string&, const hidl_string&, int32_t));

};

+176 −48
Original line number Diff line number Diff line
@@ -28,31 +28,60 @@
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <hidl/ServiceManagement.h>

template <typename A, typename B, typename C, typename D, typename E>
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,
        const A &a, const B &b, const C &c, const D &d, const E &e) {
        const A &a, const B &b, const C &c, const D &d, const E &, const F &f) {
    using namespace ::std;
    stream << left
           << setw(70) << a << "\t"
           << setw(20) << b << "\t"
           << setw(10) << c << "\t"
           << setw(5)  << d << "\t"
           << setw(0)  << e
           // TODO(b/34984175): enable selecting columns
           // << setw(16) << e << "\t"
           << setw(0)  << f
           << 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;
    return os.str();
}

::android::status_t getReferencedPids(
std::pair<hidl_string, hidl_string> split(const hidl_string &s, char c) {
    const char *pos = strchr(s.c_str(), c);
    if (pos == nullptr) {
        return {s, {}};
    }
    return {hidl_string(s.c_str(), pos - s.c_str()), hidl_string(pos + 1)};
}

bool getReferencedPids(
        pid_t serverPid, std::map<uint64_t, std::string> *objects) {

    std::ifstream ifs("/d/binder/proc/" + std::to_string(serverPid));
    if (!ifs.is_open()) {
        return ::android::PERMISSION_DENIED;
        return false;
    }

    static const std::regex prefix("^\\s*node \\d+:\\s+u([0-9a-f]+)\\s+c([0-9a-f]+)\\s+");
@@ -77,66 +106,165 @@ std::string toHexString(uint64_t t) {
            (*objects)[ptr] += line.substr(pos + proc.size());
        }
    }
    return ::android::OK;
    return true;
}


int dump() {
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;
    }
}

    std::map<std::string, ::android::sp<IServiceManager>> mapping = {
            {"hwbinder", defaultServiceManager()},
            {"passthrough", getPassthroughServiceManager()}
    };

    std::stringstream stream;

    stream << "All services:" << endl;
    stream << left;
    printColumn(stream, "Interface", "Instance", "Transport", "Server", "Clients");

    for (const auto &pair : mapping) {
        const std::string &mode = pair.first;
        const ::android::sp<IServiceManager> &manager = pair.second;
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) {

        if (manager == nullptr) {
            cerr << "Failed to get IServiceManager for " << mode << "!" << endl;
            continue;
            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;
    }
}

        auto ret = manager->debugDump([&](const auto &registered) {
void dumpBinderized(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 listRet = manager->list([&] (const auto &fqInstanceNames) {
        // server pid, .ptr value of binder object, child pids
        std::map<std::string, DebugInfo> allDebugInfos;
        std::map<pid_t, std::map<uint64_t, std::string>> allPids;
            for (const auto &info : registered) {
                if (info.pid < 0) {
        for (const auto &fqInstanceName : fqInstanceNames) {
            const auto pair = split(fqInstanceName, '/');
            const auto &serviceName = pair.first;
            const auto &instanceName = pair.second;
            auto getRet = manager->get(serviceName, instanceName);
            if (!getRet.isOk()) {
                cerr << "Warning: Skipping \"" << fqInstanceName << "\": "
                     << "cannot be fetched from service manager:"
                     << getRet.description() << endl;
                continue;
            }
            sp<IBase> service = getRet;
            if (service == nullptr) {
                cerr << "Warning: Skipping \"" << fqInstanceName << "\": "
                     << "cannot be fetched from service manager (null)";
                continue;
            }
                pid_t serverPid = info.pid;
                allPids[serverPid].clear();
            auto debugRet = service->getDebugInfo([&] (const auto &debugInfo) {
                allDebugInfos[fqInstanceName] = debugInfo;
                if (debugInfo.pid >= 0) {
                    allPids[static_cast<pid_t>(debugInfo.pid)].clear();
                }
            });
            if (!debugRet.isOk()) {
                cerr << "Warning: Skipping \"" << fqInstanceName << "\": "
                     << "debugging information cannot be retrieved:"
                     << debugRet.description() << endl;
            }
        }
        for (auto &pair : allPids) {
            pid_t serverPid = pair.first;
                if (getReferencedPids(serverPid, &allPids[serverPid]) != ::android::OK) {
            if (!getReferencedPids(serverPid, &allPids[serverPid])) {
                std::cerr << "Warning: no information for PID " << serverPid
                          << ", are you root?" << std::endl;
            }
        }
            for (const auto &info : registered) {
        for (const auto &fqInstanceName : fqInstanceNames) {
            const auto pair = split(fqInstanceName, '/');
            const auto &serviceName = pair.first;
            const auto &instanceName = pair.second;
            auto it = allDebugInfos.find(fqInstanceName);
            if (it == allDebugInfos.end()) {
                printColumn(stream,
                    info.interfaceName,
                    info.instanceName.empty() ? "N/A" : info.instanceName,
                    serviceName,
                    instanceName,
                    mode,
                    "N/A",
                    "N/A",
                    ""
                );
                continue;
            }
            const DebugInfo &info = it->second;
            printColumn(stream,
                serviceName,
                instanceName,
                mode,
                info.pid < 0 ? "N/A" : std::to_string(info.pid),
                    info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]);
                info.ptr == 0 ? "N/A" : toHexString(info.ptr),
                info.pid < 0 || info.ptr == 0 ? "" : allPids[info.pid][info.ptr]
            );
        }

    });
        if (!ret.isOk()) {
            cerr << "Failed to list services for " << mode << ": "
                 << ret.description() << endl;
    if (!listRet.isOk()) {
        cerr << "Error: Failed to list services for " << mode << ": "
             << listRet.description() << endl;
    }
}

int dump() {
    using namespace ::std;
    using namespace ::android::hardware;

    std::stringstream stream;

    stream << "All services:" << endl;
    stream << left;
    printColumn(stream, "Interface", "Instance", "Transport", "Server", "PTR", "Clients");

    auto bManager = defaultServiceManager();
    if (bManager == nullptr) {
        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();
    return 0;
}