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

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

Merge changes from topic "lshal_lazy_hals" am: e3a52f01

am: 7ed23273

Change-Id: Ifa1d75cf32611b5bef4232282e96fccc4fc80c59
parents 36479727 7ed23273
Loading
Loading
Loading
Loading
+195 −53
Original line number Diff line number Diff line
@@ -57,6 +57,19 @@ vintf::SchemaType toSchemaType(Partition p) {
    return (p == Partition::SYSTEM) ? vintf::SchemaType::FRAMEWORK : vintf::SchemaType::DEVICE;
}

Partition toPartition(vintf::SchemaType t) {
    switch (t) {
        case vintf::SchemaType::FRAMEWORK: return Partition::SYSTEM;
        // TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
        case vintf::SchemaType::DEVICE: return Partition::VENDOR;
    }
    return Partition::UNKNOWN;
}

std::string getPackageAndVersion(const std::string& fqInstance) {
    return splitFirst(fqInstance, ':').first;
}

NullableOStream<std::ostream> ListCommand::out() const {
    return mLshal.out();
}
@@ -77,6 +90,8 @@ std::string ListCommand::parseCmdline(pid_t pid) const {
}

const std::string &ListCommand::getCmdline(pid_t pid) {
    static const std::string kEmptyString{};
    if (pid == NO_PID) return kEmptyString;
    auto pair = mCmdlines.find(pid);
    if (pair != mCmdlines.end()) {
        return pair->second;
@@ -93,6 +108,7 @@ void ListCommand::removeDeadProcesses(Pids *pids) {
}

Partition ListCommand::getPartition(pid_t pid) {
    if (pid == NO_PID) return Partition::UNKNOWN;
    auto it = mPartitions.find(pid);
    if (it != mPartitions.end()) {
        return it->second;
@@ -176,7 +192,7 @@ VintfInfo ListCommand::getVintfInfo(const std::string& fqInstanceName,
    FqInstance fqInstance;
    if (!fqInstance.setTo(fqInstanceName) &&
        // Ignore interface / instance for passthrough libs
        !fqInstance.setTo(splitFirst(fqInstanceName, ':').first)) {
        !fqInstance.setTo(getPackageAndVersion(fqInstanceName))) {
        err() << "Warning: Cannot parse '" << fqInstanceName << "'; no VINTF info." << std::endl;
        return VINTF_INFO_EMPTY;
    }
@@ -283,36 +299,39 @@ const PidInfo* ListCommand::getPidInfoCached(pid_t serverPid) {
    return &pair.first->second;
}

bool ListCommand::shouldReportHalType(const HalType &type) const {
    return (std::find(mListTypes.begin(), mListTypes.end(), type) != mListTypes.end());
bool ListCommand::shouldFetchHalType(const HalType &type) const {
    return (std::find(mFetchTypes.begin(), mFetchTypes.end(), type) != mFetchTypes.end());
}

void ListCommand::forEachTable(const std::function<void(Table &)> &f) {
    for (const auto& type : mListTypes) {
Table* ListCommand::tableForType(HalType type) {
    switch (type) {
        case HalType::BINDERIZED_SERVICES:
                f(mServicesTable); break;
            return &mServicesTable;
        case HalType::PASSTHROUGH_CLIENTS:
                f(mPassthroughRefTable); break;
            return &mPassthroughRefTable;
        case HalType::PASSTHROUGH_LIBRARIES:
                f(mImplementationsTable); break;
            return &mImplementationsTable;
        case HalType::VINTF_MANIFEST:
            return &mManifestHalsTable;
        case HalType::LAZY_HALS:
            return &mLazyHalsTable;
        default:
                LOG(FATAL) << __func__ << "Unknown HAL type.";
            LOG(FATAL) << "Unknown HAL type " << static_cast<int64_t>(type);
            return nullptr;
    }
}
const Table* ListCommand::tableForType(HalType type) const {
    return const_cast<ListCommand*>(this)->tableForType(type);
}
void ListCommand::forEachTable(const std::function<void(const Table &)> &f) const {

void ListCommand::forEachTable(const std::function<void(Table &)> &f) {
    for (const auto& type : mListTypes) {
        switch (type) {
            case HalType::BINDERIZED_SERVICES:
                f(mServicesTable); break;
            case HalType::PASSTHROUGH_CLIENTS:
                f(mPassthroughRefTable); break;
            case HalType::PASSTHROUGH_LIBRARIES:
                f(mImplementationsTable); break;
            default:
                LOG(FATAL) << __func__ << "Unknown HAL type.";
        f(*tableForType(type));
    }
}
void ListCommand::forEachTable(const std::function<void(const Table &)> &f) const {
    for (const auto& type : mListTypes) {
        f(*tableForType(type));
    }
}

@@ -329,7 +348,9 @@ void ListCommand::postprocess() {
            }
        }
        for (TableEntry& entry : table) {
            if (entry.partition == Partition::UNKNOWN) {
                entry.partition = getPartition(entry.serverPid);
            }
            entry.vintfInfo = getVintfInfo(entry.interfaceName, {entry.transport, entry.arch});
        }
    });
@@ -366,6 +387,12 @@ void ListCommand::postprocess() {
    mImplementationsTable.setDescription(
            "All available passthrough implementations (all -impl.so files).\n"
            "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,
@@ -416,7 +443,7 @@ bool ListCommand::addEntryWithInstance(const TableEntry& entry,

bool ListCommand::addEntryWithoutInstance(const TableEntry& entry,
                                          const vintf::HalManifest* manifest) const {
    const auto& packageAndVersion = splitFirst(splitFirst(entry.interfaceName, ':').first, '@');
    const auto& packageAndVersion = splitFirst(getPackageAndVersion(entry.interfaceName), '@');
    const auto& package = packageAndVersion.first;
    vintf::Version version;
    if (!vintf::parse(packageAndVersion.second, &version)) {
@@ -446,6 +473,8 @@ void ListCommand::dumpVintf(const NullableOStream<std::ostream>& out) const {
        if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);
    for (const TableEntry& entry : mPassthroughRefTable)
        if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);
    for (const TableEntry& entry : mManifestHalsTable)
        if (!addEntryWithInstance(entry, &manifest)) error.push_back(entry.interfaceName);

    std::vector<std::string> passthrough;
    for (const TableEntry& entry : mImplementationsTable)
@@ -503,8 +532,11 @@ static vintf::Arch fromBaseArchitecture(::android::hidl::base::V1_0::DebugInfo::

void ListCommand::dumpTable(const NullableOStream<std::ostream>& out) const {
    if (mNeat) {
        MergedTable({&mServicesTable, &mPassthroughRefTable, &mImplementationsTable})
            .createTextTable().dump(out.buf());
        std::vector<const Table*> tables;
        forEachTable([&tables](const Table &table) {
            tables.push_back(&table);
        });
        MergedTable(std::move(tables)).createTextTable().dump(out.buf());
        return;
    }

@@ -552,25 +584,12 @@ Status ListCommand::dump() {
    return OK;
}

void ListCommand::putEntry(TableEntrySource source, TableEntry &&entry) {
    Table *table = nullptr;
    switch (source) {
        case HWSERVICEMANAGER_LIST :
            table = &mServicesTable; break;
        case PTSERVICEMANAGER_REG_CLIENT :
            table = &mPassthroughRefTable; break;
        case LIST_DLLIB :
            table = &mImplementationsTable; break;
        default:
            err() << "Error: Unknown source of entry " << source << std::endl;
    }
    if (table) {
        table->add(std::forward<TableEntry>(entry));
    }
void ListCommand::putEntry(HalType type, TableEntry &&entry) {
    tableForType(type)->add(std::forward<TableEntry>(entry));
}

Status ListCommand::fetchAllLibraries(const sp<IServiceManager> &manager) {
    if (!shouldReportHalType(HalType::PASSTHROUGH_LIBRARIES)) { return OK; }
    if (!shouldFetchHalType(HalType::PASSTHROUGH_LIBRARIES)) { return OK; }

    using namespace ::android::hardware;
    using namespace ::android::hidl::manager::V1_0;
@@ -588,7 +607,7 @@ Status ListCommand::fetchAllLibraries(const sp<IServiceManager> &manager) {
            }).first->second.arch |= fromBaseArchitecture(info.arch);
        }
        for (auto &&pair : entries) {
            putEntry(LIST_DLLIB, std::move(pair.second));
            putEntry(HalType::PASSTHROUGH_LIBRARIES, std::move(pair.second));
        }
    });
    if (!ret.isOk()) {
@@ -600,7 +619,7 @@ Status ListCommand::fetchAllLibraries(const sp<IServiceManager> &manager) {
}

Status ListCommand::fetchPassthrough(const sp<IServiceManager> &manager) {
    if (!shouldReportHalType(HalType::PASSTHROUGH_CLIENTS)) { return OK; }
    if (!shouldFetchHalType(HalType::PASSTHROUGH_CLIENTS)) { return OK; }

    using namespace ::android::hardware;
    using namespace ::android::hardware::details;
@@ -611,7 +630,7 @@ Status ListCommand::fetchPassthrough(const sp<IServiceManager> &manager) {
            if (info.clientPids.size() <= 0) {
                continue;
            }
            putEntry(PTSERVICEMANAGER_REG_CLIENT, {
            putEntry(HalType::PASSTHROUGH_CLIENTS, {
                .interfaceName =
                        std::string{info.interfaceName.c_str()} + "/" +
                        std::string{info.instanceName.c_str()},
@@ -633,7 +652,7 @@ Status ListCommand::fetchPassthrough(const sp<IServiceManager> &manager) {
Status ListCommand::fetchBinderized(const sp<IServiceManager> &manager) {
    using vintf::operator<<;

    if (!shouldReportHalType(HalType::BINDERIZED_SERVICES)) { return OK; }
    if (!shouldFetchHalType(HalType::BINDERIZED_SERVICES)) { return OK; }

    const vintf::Transport mode = vintf::Transport::HWBINDER;
    hidl_vec<hidl_string> fqInstanceNames;
@@ -654,12 +673,13 @@ Status ListCommand::fetchBinderized(const sp<IServiceManager> &manager) {
        TableEntry& entry = allTableEntries[fqInstanceName];
        entry.interfaceName = fqInstanceName;
        entry.transport = mode;
        entry.serviceStatus = ServiceStatus::NON_RESPONSIVE;

        status |= fetchBinderizedEntry(manager, &entry);
    }

    for (auto& pair : allTableEntries) {
        putEntry(HWSERVICEMANAGER_LIST, std::move(pair.second));
        putEntry(HalType::BINDERIZED_SERVICES, std::move(pair.second));
    }
    return status;
}
@@ -759,9 +779,100 @@ Status ListCommand::fetchBinderizedEntry(const sp<IServiceManager> &manager,
            handleError(TRANSACTION_ERROR, "getHashChain failed: " + hashRet.description());
        }
    } while (0);
    if (status == OK) {
        entry->serviceStatus = ServiceStatus::ALIVE;
    }
    return status;
}

Status ListCommand::fetchManifestHals() {
    if (!shouldFetchHalType(HalType::VINTF_MANIFEST)) { return OK; }
    Status status = OK;

    for (auto manifest : {getDeviceManifest(), getFrameworkManifest()}) {
        if (manifest == nullptr) {
            status |= VINTF_ERROR;
            continue;
        }

        std::map<std::string, TableEntry> entries;

        manifest->forEachInstance([&] (const vintf::ManifestInstance& manifestInstance) {
            TableEntry entry{
                .interfaceName = manifestInstance.getFqInstance().string(),
                .transport = manifestInstance.transport(),
                .arch = manifestInstance.arch(),
                // TODO(b/71555570): Device manifest does not distinguish HALs from vendor or ODM.
                .partition = toPartition(manifest->type()),
                .serviceStatus = ServiceStatus::DECLARED};
            std::string key = entry.interfaceName;
            entries.emplace(std::move(key), std::move(entry));
            return true;
        });

        for (auto&& pair : entries)
            mManifestHalsTable.add(std::move(pair.second));
    }
    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();
@@ -781,9 +892,27 @@ Status ListCommand::fetch() {
    } else {
        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() {
    int v = mOptions.size();
    // A list of acceptable command line options
@@ -847,6 +976,14 @@ void ListCommand::registerAllOptions() {
       "    - DC: device compatibility matrix\n"
       "    - FM: framework manifest\n"
       "    - FC: framework compatibility matrix"});
    mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
        thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
        return OK;
    }, "print service status column. Possible values are:\n"
       "    - alive: alive and running hwbinder service;\n"
       "    - registered;dead: registered to hwservicemanager but is not responsive;\n"
       "    - declared: only declared in VINTF manifest but is not registered to hwservicemanager;\n"
       "    - N/A: no information for passthrough HALs."});

    // long options without short alternatives
    mOptions.push_back({'\0', "init-vintf", no_argument, v++, [](ListCommand* thiz, const char* arg) {
@@ -887,7 +1024,11 @@ void ListCommand::registerAllOptions() {
            {"passthrough_clients", HalType::PASSTHROUGH_CLIENTS},
            {"c", HalType::PASSTHROUGH_CLIENTS},
            {"passthrough_libs", HalType::PASSTHROUGH_LIBRARIES},
            {"l", HalType::PASSTHROUGH_LIBRARIES}
            {"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), ',');
@@ -911,9 +1052,9 @@ void ListCommand::registerAllOptions() {

        if (thiz->mListTypes.empty()) { return USAGE; }
        return OK;
    }, "comma-separated list of one or more HAL types.\nThe output is restricted to the selected "
       "association(s). Valid options\nare: (b|binderized), (c|passthrough_clients), and (l|"
       "passthrough_libs).\nBy default, lists all available HALs."});
    }, "comma-separated list of one or more sections.\nThe output is restricted to the selected "
       "section(s). Valid options\nare: (b|binderized), (c|passthrough_clients), (l|"
       "passthrough_libs), and (v|vintf).\nDefault is `bcl`."});
}

// Create 'longopts' argument to getopt_long. Caller is responsible for maintaining
@@ -1030,6 +1171,7 @@ Status ListCommand::parseArgs(const Arg &arg) {
        mListTypes = {HalType::BINDERIZED_SERVICES, HalType::PASSTHROUGH_CLIENTS,
                      HalType::PASSTHROUGH_LIBRARIES};
    }
    initFetchTypes();

    forEachTable([this] (Table& table) {
        table.setSelectedColumns(this->mSelectedColumns);
@@ -1068,7 +1210,7 @@ void ListCommand::usage() const {
    err() << "list:" << std::endl
          << "    lshal" << std::endl
          << "    lshal list" << std::endl
          << "        List all hals with default ordering and columns (`lshal list -riepc`)" << std::endl
          << "        List all hals with default ordering and columns (`lshal list -liepc`)" << std::endl
          << "    lshal list [-h|--help]" << std::endl
          << "        -h, --help: Print help message for list (`lshal help list`)" << std::endl
          << "    lshal [list] [OPTIONS...]" << std::endl;
+22 −7
Original line number Diff line number Diff line
@@ -50,7 +50,9 @@ struct PidInfo {
enum class HalType {
    BINDERIZED_SERVICES = 0,
    PASSTHROUGH_CLIENTS,
    PASSTHROUGH_LIBRARIES
    PASSTHROUGH_LIBRARIES,
    VINTF_MANIFEST,
    LAZY_HALS,
};

class ListCommand : public Command {
@@ -93,10 +95,12 @@ protected:
    // Retrieve derived information base on existing table
    virtual void postprocess();
    Status dump();
    void putEntry(TableEntrySource source, TableEntry &&entry);
    void putEntry(HalType type, TableEntry &&entry);
    Status fetchPassthrough(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
    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);
@@ -134,6 +138,8 @@ protected:

    void forEachTable(const std::function<void(Table &)> &f);
    void forEachTable(const std::function<void(const Table &)> &f) const;
    Table* tableForType(HalType type);
    const Table* tableForType(HalType type) const;

    NullableOStream<std::ostream> err() const;
    NullableOStream<std::ostream> out() const;
@@ -144,12 +150,20 @@ protected:
    bool addEntryWithInstance(const TableEntry &entry, vintf::HalManifest *manifest) const;
    bool addEntryWithoutInstance(const TableEntry &entry, const vintf::HalManifest *manifest) const;

    // Helper function. Whether to list entries corresponding to a given HAL type.
    bool shouldReportHalType(const HalType &type) const;
    // Helper function. Whether to fetch entries corresponding to a given HAL type.
    bool shouldFetchHalType(const HalType &type) const;

    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;
@@ -163,9 +177,10 @@ protected:
    // If true, explanatory text are not emitted.
    bool mNeat = false;

    // Type(s) of HAL associations to list. By default, report all.
    std::vector<HalType> mListTypes{HalType::BINDERIZED_SERVICES, HalType::PASSTHROUGH_CLIENTS,
                                    HalType::PASSTHROUGH_LIBRARIES};
    // Type(s) of HAL associations to list.
    std::vector<HalType> mListTypes{};
    // Type(s) of HAL associations to fetch.
    std::set<HalType> mFetchTypes{};

    // If an entry does not exist, need to ask /proc/{pid}/cmdline to get it.
    // If an entry exist but is an empty string, process might have died.
+15 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ static std::string getTitle(TableColumnType type) {
        case TableColumnType::RELEASED:         return "R";
        case TableColumnType::HASH:             return "Hash";
        case TableColumnType::VINTF:            return "VINTF";
        case TableColumnType::SERVICE_STATUS:   return "Status";
        default:
            LOG(FATAL) << __func__ << "Should not reach here. " << static_cast<int>(type);
            return "";
@@ -94,6 +95,8 @@ std::string TableEntry::getField(TableColumnType type) const {
            return hash;
        case TableColumnType::VINTF:
            return getVintfInfo();
        case TableColumnType::SERVICE_STATUS:
            return lshal::to_string(serviceStatus);
        default:
            LOG(FATAL) << __func__ << "Should not reach here. " << static_cast<int>(type);
            return "";
@@ -129,6 +132,18 @@ std::string TableEntry::getVintfInfo() const {
    return joined.empty() ? "X" : joined;
}

std::string to_string(ServiceStatus s) {
    switch (s) {
        case ServiceStatus::ALIVE: return "alive";
        case ServiceStatus::NON_RESPONSIVE: return "non-responsive";
        case ServiceStatus::DECLARED: return "declared";
        case ServiceStatus::UNKNOWN: return "N/A";
    }

    LOG(FATAL) << __func__ << "Should not reach here." << static_cast<int>(s);
    return "";
}

TextTable Table::createTextTable(bool neat,
    const std::function<std::string(const std::string&)>& emitDebugInfo) const {

+11 −7
Original line number Diff line number Diff line
@@ -35,13 +35,6 @@ namespace lshal {
using android::procpartition::Partition;
using Pids = std::vector<int32_t>;

enum : unsigned int {
    HWSERVICEMANAGER_LIST, // through defaultServiceManager()->list()
    PTSERVICEMANAGER_REG_CLIENT, // through registerPassthroughClient
    LIST_DLLIB, // through listing dynamic libraries
};
using TableEntrySource = unsigned int;

enum class TableColumnType : unsigned int {
    INTERFACE_NAME,
    TRANSPORT,
@@ -55,6 +48,7 @@ enum class TableColumnType : unsigned int {
    RELEASED,
    HASH,
    VINTF,
    SERVICE_STATUS,
};

enum : unsigned int {
@@ -71,6 +65,14 @@ enum {
    NO_PTR = 0
};

enum class ServiceStatus {
    UNKNOWN, // For passthrough
    ALIVE,
    NON_RESPONSIVE, // registered but not respond to calls
    DECLARED, // in VINTF manifest
};
std::string to_string(ServiceStatus s);

struct TableEntry {
    std::string interfaceName{};
    vintf::Transport transport{vintf::Transport::EMPTY};
@@ -86,6 +88,8 @@ struct TableEntry {
    std::string hash{};
    Partition partition{Partition::UNKNOWN};
    VintfInfo vintfInfo{VINTF_INFO_EMPTY};
    // true iff hwbinder and service started
    ServiceStatus serviceStatus{ServiceStatus::UNKNOWN};

    static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
        return a.interfaceName < b.interfaceName;
+78 −14

File changed.

Preview size limit exceeded, changes collapsed.

Loading