summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Hong <elsk@google.com>2017-02-13 17:51:59 -0800
committerYifan Hong <elsk@google.com>2017-02-14 19:25:27 -0800
commit38d53e0327f200a8a16f99d1e1a09e33c2be8e81 (patch)
treea404e1519c22613191e775dab4d88dca31289dec
parentb0dde932ad8989a393fad148c17817bcb2ff7a43 (diff)
downloadnative-38d53e0327f200a8a16f99d1e1a09e33c2be8e81.tar.gz
lshal: Allow selecting columns and sorting by column.
Examples: see tests below. Test: lshal Test: lshal -intpac Test: lshal --sort=i Test: lshal --sort=p Bug: 34984175 Change-Id: Ia09823776a206868a5d58a2ede153a4538147756
-rw-r--r--cmds/lshal/Lshal.cpp109
-rw-r--r--cmds/lshal/Lshal.h10
-rw-r--r--cmds/lshal/TableEntry.h19
3 files changed, 115 insertions, 23 deletions
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index e6d10bfc06..d213fd314f 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -35,20 +35,6 @@ using ::android::hidl::manager::V1_0::IServiceManager;
namespace android {
namespace lshal {
-template <typename A, typename C, typename D, typename E, typename F>
-void printColumn(std::ostream &stream,
- const A &a, const C &c, const D &d, const E &, const F &f) {
- using namespace ::std;
- stream << left
- << setw(80) << a << "\t"
- << setw(10) << c << "\t"
- << setw(5) << d << "\t"
- // TODO(b/34984175): enable selecting columns
- // << setw(16) << e << "\t"
- << setw(0) << f
- << endl;
-}
-
template <typename A>
std::string join(const A &components, const std::string &separator) {
std::stringstream out;
@@ -133,11 +119,35 @@ bool Lshal::getReferencedPids(
return true;
}
+void Lshal::postprocess() {
+ if (mSortColumn) {
+ std::sort(mTable.begin(), mTable.end(), mSortColumn);
+ }
+}
+
+void Lshal::printLine(
+ const std::string &interfaceName,
+ const std::string &transport, const std::string &server,
+ const std::string &address, const std::string &clients) const {
+ if (mSelectedColumns & ENABLE_INTERFACE_NAME)
+ mOut << std::setw(80) << interfaceName << "\t";
+ if (mSelectedColumns & ENABLE_TRANSPORT)
+ mOut << std::setw(10) << transport << "\t";
+ if (mSelectedColumns & ENABLE_SERVER_PID)
+ mOut << std::setw(5) << server << "\t";
+ if (mSelectedColumns & ENABLE_SERVER_ADDR)
+ mOut << std::setw(16) << address << "\t";
+ if (mSelectedColumns & ENABLE_CLIENT_PIDS)
+ mOut << std::setw(0) << clients;
+ mOut << std::endl;
+}
+
void Lshal::dump() const {
mOut << "All services:" << std::endl;
- printColumn(mOut, "Interface", "Transport", "Server", "PTR", "Clients");
+ mOut << std::left;
+ printLine("Interface", "Transport", "Server", "PTR", "Clients");
for (const auto &entry : mTable) {
- printColumn(mOut, entry.interfaceName,
+ printLine(entry.interfaceName,
entry.transport,
entry.serverPid == NO_PID ? "N/A" : std::to_string(entry.serverPid),
entry.serverObjectAddress == NO_PTR ? "N/A" : toHexString(entry.serverObjectAddress),
@@ -305,16 +315,35 @@ Status Lshal::fetch() {
void Lshal::usage() const {
mErr
<< "usage: lshal" << std::endl
- << " To dump all hals." << std::endl
- << "or:" << std::endl
+ << " Dump all hals with default ordering and columns [-itpc]." << std::endl
+ << " lshal [--interface|-i] [--transport|-t]" << std::endl
+ << " [--pid|-p] [--address|-a] [--clients|-c] [--cmdline|-m]" << std::endl
+ << " [--sort={interface|i|pid|p}]" << std::endl
+ << " -i, --interface: print the interface name column" << std::endl
+ << " -n, --instance: print the instance name column" << std::endl
+ << " -t, --transport: print the transport mode column" << std::endl
+ << " -p, --pid: print the server PID column" << std::endl
+ << " -a, --address: print the server object address column" << std::endl
+ << " -c, --clients: print the client PIDs column" << std::endl
+ << " --sort=i, --sort=interface: sort by interface name" << std::endl
+ << " --sort=p, --sort=pid: sort by server pid" << std::endl
<< " lshal [-h|--help]" << std::endl
<< " -h, --help: show this help information." << std::endl;
}
Status Lshal::parseArgs(int argc, char **argv) {
static struct option longOptions[] = {
- {"help", no_argument, 0, 'h' },
- { 0, 0, 0, 0 }
+ // long options with short alternatives
+ {"help", no_argument, 0, 'h' },
+ {"interface", no_argument, 0, 'i' },
+ {"transport", no_argument, 0, 't' },
+ {"pid", no_argument, 0, 'p' },
+ {"address", no_argument, 0, 'a' },
+ {"clients", no_argument, 0, 'c' },
+
+ // long options without short alternatives
+ {"sort", required_argument, 0, 's' },
+ { 0, 0, 0, 0 }
};
int optionIndex;
@@ -322,17 +351,54 @@ Status Lshal::parseArgs(int argc, char **argv) {
optind = 1;
for (;;) {
// using getopt_long in case we want to add other options in the future
- c = getopt_long(argc, argv, "h", longOptions, &optionIndex);
+ c = getopt_long(argc, argv, "hitpac", longOptions, &optionIndex);
if (c == -1) {
break;
}
switch (c) {
+ case 's': {
+ if (strcmp(optarg, "interface") == 0 || strcmp(optarg, "i") == 0) {
+ mSortColumn = TableEntry::sortByInterfaceName;
+ } else if (strcmp(optarg, "pid") == 0 || strcmp(optarg, "p") == 0) {
+ mSortColumn = TableEntry::sortByServerPid;
+ } else {
+ mErr << "Unrecognized sorting column: " << optarg << std::endl;
+ usage();
+ return USAGE;
+ }
+ break;
+ }
+ case 'i': {
+ mSelectedColumns |= ENABLE_INTERFACE_NAME;
+ break;
+ }
+ case 't': {
+ mSelectedColumns |= ENABLE_TRANSPORT;
+ break;
+ }
+ case 'p': {
+ mSelectedColumns |= ENABLE_SERVER_PID;
+ break;
+ }
+ case 'a': {
+ mSelectedColumns |= ENABLE_SERVER_ADDR;
+ break;
+ }
+ case 'c': {
+ mSelectedColumns |= ENABLE_CLIENT_PIDS;
+ break;
+ }
case 'h': // falls through
default: // see unrecognized options
usage();
return USAGE;
}
}
+
+ if (mSelectedColumns == 0) {
+ mSelectedColumns = ENABLE_INTERFACE_NAME
+ | ENABLE_TRANSPORT | ENABLE_SERVER_PID | ENABLE_CLIENT_PIDS;
+ }
return OK;
}
@@ -342,6 +408,7 @@ int Lshal::main(int argc, char **argv) {
return status;
}
status = fetch();
+ postprocess();
dump();
return status;
}
diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h
index c87ebc3b98..d7bcab2929 100644
--- a/cmds/lshal/Lshal.h
+++ b/cmds/lshal/Lshal.h
@@ -48,6 +48,7 @@ public:
private:
Status parseArgs(int argc, char **argv);
Status fetch();
+ void postprocess();
void dump() const;
void usage() const;
void putEntry(TableEntry &&entry);
@@ -56,11 +57,16 @@ private:
Status fetchAllLibraries(const sp<::android::hidl::manager::V1_0::IServiceManager> &manager);
bool getReferencedPids(
pid_t serverPid, std::map<uint64_t, Pids> *objects) const;
+ void printLine(
+ const std::string &interfaceName,
+ const std::string &transport, const std::string &server,
+ const std::string &address, const std::string &clients) const;
-
- Table mTable;
+ Table mTable{};
std::ostream &mErr = std::cerr;
std::ostream &mOut = std::cout;
+ TableEntryCompare mSortColumn = nullptr;
+ TableEntrySelect mSelectedColumns = 0;
};
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 484df3fbf2..864b41b3f2 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <iostream>
namespace android {
namespace lshal {
@@ -33,9 +34,27 @@ struct TableEntry {
int32_t serverPid;
uint64_t serverObjectAddress;
Pids clientPids;
+
+ static bool sortByInterfaceName(const TableEntry &a, const TableEntry &b) {
+ return a.interfaceName < b.interfaceName;
+ };
+ static bool sortByServerPid(const TableEntry &a, const TableEntry &b) {
+ return a.serverPid < b.serverPid;
+ };
};
using Table = std::vector<TableEntry>;
+using TableEntryCompare = std::function<bool(const TableEntry &, const TableEntry &)>;
+
+enum : unsigned int {
+ ENABLE_INTERFACE_NAME = 1 << 0,
+ ENABLE_TRANSPORT = 1 << 1,
+ ENABLE_SERVER_PID = 1 << 2,
+ ENABLE_SERVER_ADDR = 1 << 3,
+ ENABLE_CLIENT_PIDS = 1 << 4
+};
+
+using TableEntrySelect = unsigned int;
enum {
NO_PID = -1,