diff options
author | Yifan Hong <elsk@google.com> | 2020-08-07 18:24:06 -0700 |
---|---|---|
committer | Yifan Hong <elsk@google.com> | 2020-08-07 20:02:16 -0700 |
commit | 30528a2d917aae624f01a89213147da44fee2ab9 (patch) | |
tree | fd7a79c4fd8142d287a76cabaa6f0bfe69bc2054 | |
parent | 52e3b47cae759317fb4a87df25568b897b132585 (diff) | |
download | native-30528a2d917aae624f01a89213147da44fee2ab9.tar.gz |
lshal: Add --all --types=all, and use in bugreport
Also clang-format.
When --all is specified, put "clients" at the end because it is usually
the longest.
Test: lshal --all
Test: lshal --all --cmdline
Test: lshal --types=all
Test: adb bugreport
Bug: 163060248
Change-Id: If95a18cff50d3b6ef3f70b300f16105b41ca28ed
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 4 | ||||
-rw-r--r-- | cmds/lshal/ListCommand.cpp | 110 | ||||
-rw-r--r-- | cmds/lshal/ListCommand.h | 3 | ||||
-rw-r--r-- | cmds/lshal/TableEntry.h | 14 | ||||
-rw-r--r-- | cmds/lshal/test.cpp | 69 |
5 files changed, 152 insertions, 48 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 78c09f2b5a..e2884e578c 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1237,12 +1237,12 @@ static Dumpstate::RunStatus RunDumpsysNormal() { static void DumpHals() { if (!ds.IsZipping()) { - RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"}, + RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build()); return; } DurationReporter duration_reporter("DUMP HALS"); - RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"}, + RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build()); using android::hidl::manager::V1_0::IServiceManager; diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp index a805a4844a..92958d957b 100644 --- a/cmds/lshal/ListCommand.cpp +++ b/cmds/lshal/ListCommand.cpp @@ -916,6 +916,18 @@ void ListCommand::initFetchTypes() { } } +// Get all values of enum type T, assuming the first value is 0 and the last value is T::LAST. +// T::LAST is not included in the returned list. +template <typename T> +std::vector<T> GetAllValues() { + using BaseType = std::underlying_type_t<T>; + std::vector<T> ret; + for (BaseType i = 0; i < static_cast<BaseType>(T::LAST); ++i) { + ret.push_back(static_cast<T>(i)); + } + return ret; +} + void ListCommand::registerAllOptions() { int v = mOptions.size(); // A list of acceptable command line options @@ -989,6 +1001,15 @@ void ListCommand::registerAllOptions() { " - declared: only declared in VINTF manifest but is not registered to hwservicemanager;\n" " - N/A: no information for passthrough HALs."}); + mOptions.push_back({'A', "all", no_argument, v++, + [](ListCommand* thiz, const char*) { + auto allColumns = GetAllValues<TableColumnType>(); + thiz->mSelectedColumns.insert(thiz->mSelectedColumns.end(), + allColumns.begin(), allColumns.end()); + return OK; + }, + "print all columns"}); + // long options without short alternatives mOptions.push_back({'\0', "init-vintf", no_argument, v++, [](ListCommand* thiz, const char* arg) { thiz->mVintf = true; @@ -1019,46 +1040,55 @@ void ListCommand::registerAllOptions() { thiz->mNeat = true; return OK; }, "output is machine parsable (no explanatory text).\nCannot be used with --debug."}); - mOptions.push_back({'\0', "types", required_argument, v++, [](ListCommand* thiz, const char* arg) { - if (!arg) { return USAGE; } - - static const std::map<std::string, HalType> kHalTypeMap { - {"binderized", HalType::BINDERIZED_SERVICES}, - {"b", HalType::BINDERIZED_SERVICES}, - {"passthrough_clients", HalType::PASSTHROUGH_CLIENTS}, - {"c", HalType::PASSTHROUGH_CLIENTS}, - {"passthrough_libs", 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), ','); - for (const auto& halTypeArg : halTypesArgs) { - if (halTypeArg.empty()) continue; - - const auto& halTypeIter = kHalTypeMap.find(halTypeArg); - if (halTypeIter == kHalTypeMap.end()) { - - thiz->err() << "Unrecognized HAL type: " << halTypeArg << std::endl; - return USAGE; - } - - // Append unique (non-repeated) HAL types to the reporting list - HalType halType = halTypeIter->second; - if (std::find(thiz->mListTypes.begin(), thiz->mListTypes.end(), halType) == - thiz->mListTypes.end()) { - thiz->mListTypes.push_back(halType); - } - } - - if (thiz->mListTypes.empty()) { return USAGE; } - return OK; - }, "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), (v|vintf), and (z|lazy).\nDefault is `bcl`."}); + mOptions.push_back( + {'\0', "types", required_argument, v++, + [](ListCommand* thiz, const char* arg) { + if (!arg) { + return USAGE; + } + + static const std::map<std::string, std::vector<HalType>> kHalTypeMap{ + {"binderized", {HalType::BINDERIZED_SERVICES}}, + {"b", {HalType::BINDERIZED_SERVICES}}, + {"passthrough_clients", {HalType::PASSTHROUGH_CLIENTS}}, + {"c", {HalType::PASSTHROUGH_CLIENTS}}, + {"passthrough_libs", {HalType::PASSTHROUGH_LIBRARIES}}, + {"l", {HalType::PASSTHROUGH_LIBRARIES}}, + {"vintf", {HalType::VINTF_MANIFEST}}, + {"v", {HalType::VINTF_MANIFEST}}, + {"lazy", {HalType::LAZY_HALS}}, + {"z", {HalType::LAZY_HALS}}, + {"all", GetAllValues<HalType>()}, + {"a", GetAllValues<HalType>()}, + }; + + std::vector<std::string> halTypesArgs = split(std::string(arg), ','); + for (const auto& halTypeArg : halTypesArgs) { + if (halTypeArg.empty()) continue; + + const auto& halTypeIter = kHalTypeMap.find(halTypeArg); + if (halTypeIter == kHalTypeMap.end()) { + thiz->err() << "Unrecognized HAL type: " << halTypeArg << std::endl; + return USAGE; + } + + // Append unique (non-repeated) HAL types to the reporting list + for (auto halType : halTypeIter->second) { + if (std::find(thiz->mListTypes.begin(), thiz->mListTypes.end(), halType) == + thiz->mListTypes.end()) { + thiz->mListTypes.push_back(halType); + } + } + } + + if (thiz->mListTypes.empty()) { + return USAGE; + } + return OK; + }, + "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), (v|vintf), (z|lazy), and (a|all).\nDefault is `b,c,l`."}); } // Create 'longopts' argument to getopt_long. Caller is responsible for maintaining diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h index acc0dcfc2e..412aadd7e4 100644 --- a/cmds/lshal/ListCommand.h +++ b/cmds/lshal/ListCommand.h @@ -52,6 +52,9 @@ enum class HalType { PASSTHROUGH_LIBRARIES, VINTF_MANIFEST, LAZY_HALS, + + // Not a real HalType. Used to determine all HalTypes. + LAST, }; class ListCommand : public Command { diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h index 0ff0c96d38..3c368132a5 100644 --- a/cmds/lshal/TableEntry.h +++ b/cmds/lshal/TableEntry.h @@ -35,19 +35,25 @@ using android::procpartition::Partition; using Pids = std::vector<int32_t>; enum class TableColumnType : unsigned int { - INTERFACE_NAME, + INTERFACE_NAME = 0, TRANSPORT, SERVER_PID, - SERVER_CMD, SERVER_ADDR, - CLIENT_PIDS, - CLIENT_CMDS, ARCH, THREADS, RELEASED, HASH, VINTF, SERVICE_STATUS, + CLIENT_PIDS, + + // Not a real TableColumnType. Used to determine all TableColumnTypes. + LAST, + + // Not included in all TableColumnTypes because they replace *PID(S) when the + // --cmdline option is set. + SERVER_CMD, + CLIENT_CMDS, }; enum : unsigned int { diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp index afe5d63575..9964888233 100644 --- a/cmds/lshal/test.cpp +++ b/cmds/lshal/test.cpp @@ -708,8 +708,8 @@ TEST_F(ListTest, DumpEmptyAndDuplicateHalTypes) { TEST_F(ListTest, UnknownHalType) { optind = 1; // mimic Lshal::parseArg() - EXPECT_EQ(1u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,a"}))); - EXPECT_THAT(err.str(), HasSubstr("Unrecognized HAL type: a")); + EXPECT_EQ(1u, mockList->main(createArg({"lshal", "-itrepac", "--types=c,r"}))); + EXPECT_THAT(err.str(), HasSubstr("Unrecognized HAL type: r")); } TEST_F(ListTest, Vintf) { @@ -793,6 +793,71 @@ TEST_F(ListTest, Vintf) { EXPECT_EQ("", err.str()); } +TEST_F(ListTest, AllColumns) { + // clang-format off + const std::string expected = + "[fake description 0]\n" + "Interface Transport Server PTR Arch Thread Use R Hash VINTF Status Clients\n" + "a.h.foo1@1.0::IFoo/1 hwbinder 1 0000000000002711 64 11/21 N 0000000000000000000000000000000000000000000000000000000000000000 X alive 2 4\n" + "a.h.foo2@2.0::IFoo/2 hwbinder 2 0000000000002712 64 12/22 Y 0202020202020202020202020202020202020202020202020202020202020202 X alive 3 5\n" + "\n" + "[fake description 1]\n" + "Interface Transport Server PTR Arch Thread Use R Hash VINTF Status Clients\n" + "a.h.foo3@3.0::IFoo/3 passthrough N/A N/A 32 N/A ? X N/A 4 6\n" + "a.h.foo4@4.0::IFoo/4 passthrough N/A N/A 32 N/A ? X N/A 5 7\n" + "\n" + "[fake description 2]\n" + "Interface Transport Server PTR Arch Thread Use R Hash VINTF Status Clients\n" + "a.h.foo5@5.0::IFoo/5 passthrough N/A N/A 32 N/A ? X N/A 6 8\n" + "a.h.foo6@6.0::IFoo/6 passthrough N/A N/A 32 N/A ? X N/A 7 9\n" + "\n"; + // clang-format on + + optind = 1; // mimic Lshal::parseArg() + EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--all"}))); + EXPECT_EQ(expected, out.str()); + EXPECT_EQ("", err.str()); +} + +TEST_F(ListTest, AllColumnsWithCmd) { + // clang-format off + const std::string expected = + "[fake description 0]\n" + "Interface Transport Server CMD PTR Arch Thread Use R Hash VINTF Status Clients CMD\n" + "a.h.foo1@1.0::IFoo/1 hwbinder command_line_1 0000000000002711 64 11/21 N 0000000000000000000000000000000000000000000000000000000000000000 X alive command_line_2;command_line_4\n" + "a.h.foo2@2.0::IFoo/2 hwbinder command_line_2 0000000000002712 64 12/22 Y 0202020202020202020202020202020202020202020202020202020202020202 X alive command_line_3;command_line_5\n" + "\n" + "[fake description 1]\n" + "Interface Transport Server CMD PTR Arch Thread Use R Hash VINTF Status Clients CMD\n" + "a.h.foo3@3.0::IFoo/3 passthrough N/A 32 N/A ? X N/A command_line_4;command_line_6\n" + "a.h.foo4@4.0::IFoo/4 passthrough N/A 32 N/A ? X N/A command_line_5;command_line_7\n" + "\n" + "[fake description 2]\n" + "Interface Transport Server CMD PTR Arch Thread Use R Hash VINTF Status Clients CMD\n" + "a.h.foo5@5.0::IFoo/5 passthrough N/A 32 N/A ? X N/A command_line_6;command_line_8\n" + "a.h.foo6@6.0::IFoo/6 passthrough N/A 32 N/A ? X N/A command_line_7;command_line_9\n" + "\n"; + // clang-format on + + optind = 1; // mimic Lshal::parseArg() + EXPECT_EQ(0u, mockList->main(createArg({"lshal", "-Am"}))); + EXPECT_EQ(expected, out.str()); + EXPECT_EQ("", err.str()); +} + +TEST_F(ListTest, AllSections) { + optind = 1; // mimic Lshal::parseArg() + EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--types=all"}))); + using HalTypeBase = std::underlying_type_t<HalType>; + for (HalTypeBase i = 0; i < static_cast<HalTypeBase>(HalType::LAST); ++i) { + EXPECT_THAT(out.str(), HasSubstr("[fake description " + std::to_string(i) + "]")); + } + EXPECT_THAT(out.str(), + Not(HasSubstr("[fake description " + + std::to_string(static_cast<HalTypeBase>(HalType::LAST)) + "]"))); + EXPECT_EQ("", err.str()); +} + // Fake service returned by mocked IServiceManager::get for DumpDebug. // The interfaceChain and getHashChain functions returns // foo(id - 1) -> foo(id - 2) -> ... foo1 -> IBase. |