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
This commit is contained in:
parent
52e3b47cae
commit
30528a2d91
5 changed files with 147 additions and 43 deletions
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
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},
|
||||
};
|
||||
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;
|
||||
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()) {
|
||||
const auto& halTypeIter = kHalTypeMap.find(halTypeArg);
|
||||
if (halTypeIter == kHalTypeMap.end()) {
|
||||
thiz->err() << "Unrecognized HAL type: " << halTypeArg << std::endl;
|
||||
return USAGE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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`."});
|
||||
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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue