Loading cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -1307,12 +1307,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; Loading cmds/lshal/ListCommand.cpp +70 −40 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -1019,20 +1040,26 @@ 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}, 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), ','); Loading @@ -1041,24 +1068,27 @@ void ListCommand::registerAllOptions() { 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; 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; } 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`."}); }, "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 Loading cmds/lshal/ListCommand.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading cmds/lshal/TableEntry.h +10 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading cmds/lshal/test.cpp +67 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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. Loading Loading
cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -1307,12 +1307,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; Loading
cmds/lshal/ListCommand.cpp +70 −40 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -1019,20 +1040,26 @@ 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}, 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), ','); Loading @@ -1041,24 +1068,27 @@ void ListCommand::registerAllOptions() { 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; 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; } 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`."}); }, "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 Loading
cmds/lshal/ListCommand.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
cmds/lshal/TableEntry.h +10 −4 Original line number Diff line number Diff line Loading @@ -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 { Loading
cmds/lshal/test.cpp +67 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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. Loading