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

Commit 3212f177 authored by Yifan Hong's avatar Yifan Hong
Browse files

lshal: add --types=lazy|z

Add a new section to lshal that shows HALs in the manifest
  - as hwbinder HALs but not registered
  - as passthrough HALs but no impl found

Fixes: 71555570
Test: lshal_test
Test: lshal --types=z

Change-Id: I6947d9e7e08991fa2497f40c81005f885d408931
parent 13ba0a97
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
@@ -313,6 +313,8 @@ Table* ListCommand::tableForType(HalType type) {
            return &mImplementationsTable;
        case HalType::VINTF_MANIFEST:
            return &mManifestHalsTable;
        case HalType::LAZY_HALS:
            return &mLazyHalsTable;
        default:
            LOG(FATAL) << "Unknown HAL type " << static_cast<int64_t>(type);
            return nullptr;
@@ -387,6 +389,10 @@ void ListCommand::postprocess() {
            "These may return subclasses through their respective HIDL_FETCH_I* functions.");
    mManifestHalsTable.setDescription(
            "All HALs that are in VINTF manifest.");
    mLazyHalsTable.setDescription(
            "All HALs that are declared in VINTF manifest:\n"
            "   - as hwbinder HALs but are not registered to hwservicemanager, and\n"
            "   - as hwbinder/passthrough HALs with no implementation.");
}

bool ListCommand::addEntryWithInstance(const TableEntry& entry,
@@ -810,6 +816,63 @@ Status ListCommand::fetchManifestHals() {
    return status;
}

Status ListCommand::fetchLazyHals() {
    using vintf::operator<<;

    if (!shouldFetchHalType(HalType::LAZY_HALS)) { return OK; }
    Status status = OK;

    for (const TableEntry& manifestEntry : mManifestHalsTable) {
        if (manifestEntry.transport == vintf::Transport::HWBINDER) {
            if (!hasHwbinderEntry(manifestEntry)) {
                mLazyHalsTable.add(TableEntry(manifestEntry));
            }
            continue;
        }
        if (manifestEntry.transport == vintf::Transport::PASSTHROUGH) {
            if (!hasPassthroughEntry(manifestEntry)) {
                mLazyHalsTable.add(TableEntry(manifestEntry));
            }
            continue;
        }
        err() << "Warning: unrecognized transport in VINTF manifest: "
              << manifestEntry.transport;
        status |= VINTF_ERROR;
    }
    return status;
}

bool ListCommand::hasHwbinderEntry(const TableEntry& entry) const {
    for (const TableEntry& existing : mServicesTable) {
        if (existing.interfaceName == entry.interfaceName) {
            return true;
        }
    }
    return false;
}

bool ListCommand::hasPassthroughEntry(const TableEntry& entry) const {
    FqInstance entryFqInstance;
    if (!entryFqInstance.setTo(entry.interfaceName)) {
        return false; // cannot parse, so add it anyway.
    }
    for (const TableEntry& existing : mImplementationsTable) {
        FqInstance existingFqInstance;
        if (!existingFqInstance.setTo(getPackageAndVersion(existing.interfaceName))) {
            continue;
        }

        // For example, manifest may say graphics.mapper@2.1 but passthroughServiceManager
        // can only list graphics.mapper@2.0.
        if (entryFqInstance.getPackage() == existingFqInstance.getPackage() &&
            vintf::Version{entryFqInstance.getVersion()}
                .minorAtLeast(vintf::Version{existingFqInstance.getVersion()})) {
            return true;
        }
    }
    return false;
}

Status ListCommand::fetch() {
    Status status = OK;
    auto bManager = mLshal.serviceManager();
@@ -830,11 +893,24 @@ Status ListCommand::fetch() {
        status |= fetchAllLibraries(pManager);
    }
    status |= fetchManifestHals();
    status |= fetchLazyHals();
    return status;
}

void ListCommand::initFetchTypes() {
    // TODO: refactor to do polymorphism on each table (so that dependency graph is not hardcoded).
    static const std::map<HalType, std::set<HalType>> kDependencyGraph{
        {HalType::LAZY_HALS, {HalType::BINDERIZED_SERVICES,
                              HalType::PASSTHROUGH_LIBRARIES,
                              HalType::VINTF_MANIFEST}},
    };
    mFetchTypes.insert(mListTypes.begin(), mListTypes.end());
    for (HalType listType : mListTypes) {
        auto it = kDependencyGraph.find(listType);
        if (it != kDependencyGraph.end()) {
            mFetchTypes.insert(it->second.begin(), it->second.end());
        }
    }
}

void ListCommand::registerAllOptions() {
@@ -951,6 +1027,8 @@ void ListCommand::registerAllOptions() {
            {"l", HalType::PASSTHROUGH_LIBRARIES},
            {"vintf", HalType::VINTF_MANIFEST},
            {"v", HalType::VINTF_MANIFEST},
            {"lazy", HalType::LAZY_HALS},
            {"z", HalType::LAZY_HALS},
        };

        std::vector<std::string> halTypesArgs = split(std::string(arg), ',');
+7 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ enum class HalType {
    PASSTHROUGH_CLIENTS,
    PASSTHROUGH_LIBRARIES,
    VINTF_MANIFEST,
    LAZY_HALS,
};

class ListCommand : public Command {
@@ -99,6 +100,7 @@ protected:
    Status fetchBinderized(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
    Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
    Status fetchManifestHals();
    Status fetchLazyHals();

    Status fetchBinderizedEntry(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager,
                                TableEntry *entry);
@@ -153,10 +155,15 @@ protected:

    void initFetchTypes();

    // Helper functions ti add HALs that are listed in VINTF manifest to LAZY_HALS table.
    bool hasHwbinderEntry(const TableEntry& entry) const;
    bool hasPassthroughEntry(const TableEntry& entry) const;

    Table mServicesTable{};
    Table mPassthroughRefTable{};
    Table mImplementationsTable{};
    Table mManifestHalsTable{};
    Table mLazyHalsTable{};

    std::string mFileOutputPath;
    TableEntryCompare mSortColumn = nullptr;
+15 −0
Original line number Diff line number Diff line
@@ -805,6 +805,21 @@ TEST_F(ListVintfTest, ManifestHals) {
    EXPECT_EQ("", err.str());
}

TEST_F(ListVintfTest, Lazy) {
    optind = 1; // mimic Lshal::parseArg()
    EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=z", "--neat"})));
    EXPECT_THAT(out.str(), HasSubstr("a.h.bar1@1.0::IBar/1 declared hwbinder    ?"));
    EXPECT_THAT(out.str(), HasSubstr("a.h.bar2@2.0::IBar/2 declared passthrough 32+64"));
    EXPECT_EQ("", err.str());
}

TEST_F(ListVintfTest, NoLazy) {
    optind = 1; // mimic Lshal::parseArg()
    EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-iStr", "--types=b,c,l", "--neat"})));
    EXPECT_THAT(out.str(), Not(HasSubstr("IBar")));
    EXPECT_EQ("", err.str());
}

class HelpTest : public ::testing::Test {
public:
    void SetUp() override {