lshal: Lshal register commands
Register commands to the controller class Lshal to autogenerate
help messages and select the correct Command.
Test: lshal_test
Change-Id: I846aef13d77bcee328c8410dc61f2e8b4c0e0d69
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index aff4975..4f128ab 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -35,6 +35,12 @@
virtual void usage() const = 0;
+ // e.g. "list"
+ virtual std::string getName() const = 0;
+
+ // e.g. "list HALs"
+ virtual std::string getSimpleDescription() const = 0;
+
protected:
Lshal& mLshal;
};
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index d21764c..622f866 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -21,6 +21,14 @@
namespace android {
namespace lshal {
+std::string DebugCommand::getName() const {
+ return "debug";
+}
+
+std::string DebugCommand::getSimpleDescription() const {
+ return "Debug a specified HAL.";
+}
+
Status DebugCommand::parseArgs(const Arg &arg) {
if (optind >= arg.argc) {
return USAGE;
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 6b70713..9b91084 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -35,6 +35,8 @@
~DebugCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
+ std::string getSimpleDescription() const override;
+ std::string getName() const override;
private:
Status parseArgs(const Arg &arg);
diff --git a/cmds/lshal/HelpCommand.cpp b/cmds/lshal/HelpCommand.cpp
index b393f05..6773ace 100644
--- a/cmds/lshal/HelpCommand.cpp
+++ b/cmds/lshal/HelpCommand.cpp
@@ -21,6 +21,14 @@
namespace android {
namespace lshal {
+std::string HelpCommand::GetName() {
+ return "help";
+}
+
+std::string HelpCommand::getSimpleDescription() const {
+ return "Print help message.";
+}
+
Status HelpCommand::main(const Arg &arg) {
if (optind >= arg.argc) {
// `lshal help` prints global usage.
@@ -49,18 +57,17 @@
}
void HelpCommand::usage() const {
- static const std::string help =
- "help:\n"
- " lshal -h\n"
- " lshal --help\n"
- " lshal help\n"
- " Print this help message\n"
- " lshal help list\n"
- " Print help message for list\n"
- " lshal help debug\n"
- " Print help message for debug\n";
+ mLshal.err()
+ << "help:" << std::endl
+ << " lshal -h" << std::endl
+ << " lshal --help" << std::endl
+ << " lshal help" << std::endl
+ << " Print this help message" << std::endl;
+ mLshal.forEachCommand([&](const Command* e) {
+ mLshal.err() << " lshal help " << e->getName() << std::endl
+ << " Print help message for " << e->getName() << std::endl;
+ });
- mLshal.err() << help;
}
} // namespace lshal
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index 3cc0d80..cc709f8 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -35,6 +35,9 @@
~HelpCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
+ std::string getSimpleDescription() const override;
+ std::string getName() const override { return GetName(); }
+ static std::string GetName();
Status usageOfCommand(const std::string& c) const;
};
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 71ac25b..c7a41a3 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -52,6 +52,13 @@
return mLshal.err();
}
+std::string ListCommand::GetName() {
+ return "list";
+}
+std::string ListCommand::getSimpleDescription() const {
+ return "List HALs.";
+}
+
std::string ListCommand::parseCmdline(pid_t pid) const {
std::ifstream ifs("/proc/" + std::to_string(pid) + "/cmdline");
std::string cmdline;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 6defb0a..346af28 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -49,6 +49,10 @@
virtual ~ListCommand() = default;
Status main(const Arg &arg) override;
void usage() const override;
+ std::string getSimpleDescription() const override;
+ std::string getName() const override { return GetName(); }
+
+ static std::string GetName();
protected:
Status parseArgs(const Arg &arg);
Status fetch();
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index a08a02c..c6f28ac 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -34,9 +34,8 @@
using ::android::hidl::manager::V1_0::IServiceManager;
Lshal::Lshal()
- : mOut(std::cout), mErr(std::cerr),
- mServiceManager(::android::hardware::defaultServiceManager()),
- mPassthroughManager(::android::hardware::getPassthroughServiceManager()) {
+ : Lshal(std::cout, std::cerr, ::android::hardware::defaultServiceManager(),
+ ::android::hardware::getPassthroughServiceManager()) {
}
Lshal::Lshal(std::ostream &out, std::ostream &err,
@@ -46,25 +45,39 @@
mServiceManager(serviceManager),
mPassthroughManager(passthroughManager) {
+ mRegisteredCommands.push_back({std::make_unique<ListCommand>(*this)});
+ mRegisteredCommands.push_back({std::make_unique<DebugCommand>(*this)});
+ mRegisteredCommands.push_back({std::make_unique<HelpCommand>(*this)});
+}
+
+void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const {
+ for (const auto& e : mRegisteredCommands) f(e.get());
}
void Lshal::usage() {
- static const std::string helpSummary =
- "lshal: List and debug HALs.\n"
- "\n"
- "commands:\n"
- " help Print help message\n"
- " list list HALs\n"
- " debug debug a specified HAL\n"
- "\n"
- "If no command is specified, `list` is the default.\n";
+ err() << "lshal: List and debug HALs." << std::endl << std::endl
+ << "commands:" << std::endl;
- err() << helpSummary << "\n";
- selectCommand("list")->usage();
- err() << "\n";
- selectCommand("debug")->usage();
- err() << "\n";
- selectCommand("help")->usage();
+ size_t nameMaxLength = 0;
+ forEachCommand([&](const Command* e) {
+ nameMaxLength = std::max(nameMaxLength, e->getName().length());
+ });
+ bool first = true;
+ forEachCommand([&](const Command* e) {
+ if (!first) err() << std::endl;
+ first = false;
+ err() << " " << std::left << std::setw(nameMaxLength + 8) << e->getName()
+ << e->getSimpleDescription();
+ });
+ err() << std::endl << "If no command is specified, `" << ListCommand::GetName()
+ << "` is the default." << std::endl << std::endl;
+
+ first = true;
+ forEachCommand([&](const Command* e) {
+ if (!first) err() << std::endl;
+ first = false;
+ e->usage();
+ });
}
// A unique_ptr type using a custom deleter function.
@@ -135,21 +148,20 @@
}
Status Lshal::parseArgs(const Arg &arg) {
- static std::set<std::string> sAllCommands{"list", "debug", "help"};
optind = 1;
if (optind >= arg.argc) {
// no options at all.
return OK;
}
mCommand = arg.argv[optind];
- if (sAllCommands.find(mCommand) != sAllCommands.end()) {
+ if (selectCommand(mCommand) != nullptr) {
++optind;
return OK; // mCommand is set correctly
}
if (mCommand.size() > 0 && mCommand[0] == '-') {
// first argument is an option, set command to "" (which is recognized as "list")
- mCommand = "";
+ mCommand.clear();
return OK;
}
@@ -164,20 +176,14 @@
}
}
-std::unique_ptr<HelpCommand> Lshal::selectHelpCommand() {
- return std::make_unique<HelpCommand>(*this);
-}
-
-std::unique_ptr<Command> Lshal::selectCommand(const std::string& command) {
- // Default command is list
- if (command == "list" || command == "") {
- return std::make_unique<ListCommand>(*this);
+Command* Lshal::selectCommand(const std::string& command) const {
+ if (command.empty()) {
+ return selectCommand(ListCommand::GetName());
}
- if (command == "debug") {
- return std::make_unique<DebugCommand>(*this);
- }
- if (command == "help") {
- return selectHelpCommand();
+ for (const auto& e : mRegisteredCommands) {
+ if (e->getName() == command) {
+ return e.get();
+ }
}
return nullptr;
}
@@ -202,7 +208,8 @@
// bad options. Run `lshal help ${mCommand}` instead.
// For example, `lshal --unknown-option` becomes `lshal help` (prints global help)
// and `lshal list --unknown-option` becomes `lshal help list`
- return selectHelpCommand()->usageOfCommand(mCommand);
+ auto&& help = selectCommand(HelpCommand::GetName());
+ return static_cast<HelpCommand*>(help)->usageOfCommand(mCommand);
}
return status;
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index 89b38db..9f8eeaa 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -54,11 +54,12 @@
std::ostream &out,
NullableOStream<std::ostream> err) const;
- std::unique_ptr<Command> selectCommand(const std::string& command);
+ Command* selectCommand(const std::string& command) const;
+
+ void forEachCommand(const std::function<void(const Command* c)>& f) const;
private:
Status parseArgs(const Arg &arg);
- std::unique_ptr<HelpCommand> selectHelpCommand();
std::string mCommand;
Arg mCmdArgs;
@@ -68,6 +69,8 @@
sp<hidl::manager::V1_0::IServiceManager> mServiceManager;
sp<hidl::manager::V1_0::IServiceManager> mPassthroughManager;
+ std::vector<std::unique_ptr<Command>> mRegisteredCommands;
+
DISALLOW_COPY_AND_ASSIGN(Lshal);
};