diff options
author | 2017-01-21 21:29:51 +0000 | |
---|---|---|
committer | 2017-01-21 21:29:51 +0000 | |
commit | f70d82da86adc73eafb958b84038da39817ec79f (patch) | |
tree | 80fa3f42afc1b5a3db9c57f2d9e61ff2dc1593da | |
parent | e011958dc393f52f16299cf54073b117ee0adbca (diff) | |
parent | bb7afe6ac9ba568416c48eb44428578238ac12f8 (diff) |
Merge "dumpsys: add option to list hardware services." am: 4d741ebedc am: 57d82aa9fd am: 42b3ff58a6
am: bb7afe6ac9
Change-Id: I5696bb6d3175687f1107a964a53af8940667d5c8
-rw-r--r-- | cmds/dumpsys/Android.bp | 2 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.cpp | 42 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.h | 5 | ||||
-rw-r--r-- | cmds/dumpsys/main.cpp | 5 | ||||
-rw-r--r-- | cmds/dumpsys/tests/Android.bp | 4 | ||||
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 76 |
6 files changed, 125 insertions, 9 deletions
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp index 34769644d5..c5ae9d28ac 100644 --- a/cmds/dumpsys/Android.bp +++ b/cmds/dumpsys/Android.bp @@ -15,6 +15,8 @@ cc_defaults { "libutils", "liblog", "libbinder", + "android.hidl.manager@1.0", + "libhidlbase" ], clang: true, diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index f0e7200069..860b7b42de 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -45,8 +45,7 @@ using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteFully; -static int sort_func(const String16* lhs, const String16* rhs) -{ +static int sort_func(const String16* lhs, const String16* rhs) { return lhs->compare(*rhs); } @@ -55,10 +54,11 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" - " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n" + " dumpsys [-t TIMEOUT] [--help | --hw | -l | --skip SERVICES | SERVICE [ARGS]]\n" " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n" + " --hw: list all hw services running on the device\n" " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n" " SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n"); } @@ -72,16 +72,42 @@ static bool IsSkipped(const Vector<String16>& skipped, const String16& service) return false; } +static void ListHardwareServices(android::hidl::manager::V1_0::IServiceManager* hm) { + using android::hardware::hidl_vec; + using android::hardware::hidl_string; + using android::hardware::Return; + using android::sp; + + if (hm == nullptr) { + ALOGE("Unable to get hardware service manager!"); + aerr << "Failed to get hardware service manager!"; + return; + } + + Return<void> ret = hm->list([](const hidl_vec<hidl_string> ®istered){ + aout << "Currently running hardware services:" << endl; + for (const auto &service : registered) { + aout << " " << service << endl; + } + }); + + if (!ret.isOk()) { + aerr << "Failed to list hardware services: " << ret.description(); + } +} + int Dumpsys::main(int argc, char* const argv[]) { Vector<String16> services; Vector<String16> args; Vector<String16> skippedServices; bool showListOnly = false; + bool listHwOnly = false; bool skipServices = false; int timeoutArg = 10; static struct option longOptions[] = { {"skip", no_argument, 0, 0 }, {"help", no_argument, 0, 0 }, + {"hw", no_argument, 0, 0 }, { 0, 0, 0, 0 } }; @@ -105,6 +131,8 @@ int Dumpsys::main(int argc, char* const argv[]) { } else if (!strcmp(longOptions[optionIndex].name, "help")) { usage(); return 0; + } else if (!strcmp(longOptions[optionIndex].name, "hw")) { + listHwOnly = true; } break; @@ -143,11 +171,17 @@ int Dumpsys::main(int argc, char* const argv[]) { } if ((skipServices && skippedServices.empty()) || - (showListOnly && (!services.empty() || !skippedServices.empty()))) { + (showListOnly && (!services.empty() || !skippedServices.empty())) || + (listHwOnly && (skipServices || services.size() > 0 || showListOnly))) { usage(); return -1; } + if (listHwOnly) { + ListHardwareServices(hm_); + return 0; + } + if (services.empty() || showListOnly) { // gets all services services = sm_->listServices(); diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h index 2534dded13..20d515d572 100644 --- a/cmds/dumpsys/dumpsys.h +++ b/cmds/dumpsys/dumpsys.h @@ -17,18 +17,21 @@ #ifndef FRAMEWORK_NATIVE_CMD_DUMPSYS_H_ #define FRAMEWORK_NATIVE_CMD_DUMPSYS_H_ +#include <android/hidl/manager/1.0/IServiceManager.h> #include <binder/IServiceManager.h> namespace android { class Dumpsys { public: - Dumpsys(android::IServiceManager* sm) : sm_(sm) { + Dumpsys(android::IServiceManager* sm, + android::hidl::manager::V1_0::IServiceManager* hm) : sm_(sm), hm_(hm) { } int main(int argc, char* const argv[]); private: android::IServiceManager* sm_; + android::hidl::manager::V1_0::IServiceManager* hm_; }; } diff --git a/cmds/dumpsys/main.cpp b/cmds/dumpsys/main.cpp index 8ba0eba0fa..b180c98e79 100644 --- a/cmds/dumpsys/main.cpp +++ b/cmds/dumpsys/main.cpp @@ -27,6 +27,7 @@ #include <stdio.h> using namespace android; +using HServiceManager = android::hidl::manager::V1_0::IServiceManager; int main(int argc, char* const argv[]) { signal(SIGPIPE, SIG_IGN); @@ -38,6 +39,8 @@ int main(int argc, char* const argv[]) { return 20; } - Dumpsys dumpsys(sm.get()); + sp<HServiceManager> hm = HServiceManager::getService("manager"); + + Dumpsys dumpsys(sm.get(), hm.get()); return dumpsys.main(argc, argv); } diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp index 7698ed5b95..e00444fcf6 100644 --- a/cmds/dumpsys/tests/Android.bp +++ b/cmds/dumpsys/tests/Android.bp @@ -5,8 +5,12 @@ cc_test { srcs: ["dumpsys_test.cpp"], shared_libs: [ + "android.hidl.manager@1.0", "libbase", "libbinder", + "liblog", + "libhidlbase", + "libhidltransport", "libutils", ], diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index a61cb009b0..a66685d23d 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -44,6 +44,12 @@ using ::testing::internal::CaptureStdout; using ::testing::internal::GetCapturedStderr; using ::testing::internal::GetCapturedStdout; +using android::hardware::hidl_vec; +using android::hardware::hidl_string; +using android::hardware::Void; +using HServiceManager = android::hidl::manager::V1_0::IServiceManager; +using IServiceNotification = android::hidl::manager::V1_0::IServiceNotification; + class ServiceManagerMock : public IServiceManager { public: MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&)); @@ -55,6 +61,26 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD0(onAsBinder, IBinder*()); }; +class HardwareServiceManagerMock : public HServiceManager { + public: + template<typename T> + using R = android::hardware::Return<T>; // conflicts with ::testing::Return + + MOCK_METHOD2(get, R<sp<IBase>>(const hidl_string&, const hidl_string&)); + MOCK_METHOD3(add, + R<bool>(const hidl_vec<hidl_string>&, + const hidl_string&, + const sp<IBase>&)); + MOCK_METHOD1(list, R<void>(list_cb)); + MOCK_METHOD2(listByInterface, + R<void>(const hidl_string&, listByInterface_cb)); + MOCK_METHOD3(registerForNotifications, + R<bool>(const hidl_string&, + const hidl_string&, + const sp<IServiceNotification>&)); + +}; + class BinderMock : public BBinder { public: BinderMock() { @@ -84,6 +110,26 @@ Action<WriteOnFdFunction> WriteOnFd(const std::string& output) { return MakeAction(new WriteOnFdAction(output)); } +// gmock black magic to provide a WithArg<0>(List(services)) matcher +typedef void HardwareListFunction(HServiceManager::list_cb); + +class HardwareListAction : public ActionInterface<HardwareListFunction> { + public: + explicit HardwareListAction(const hidl_vec<hidl_string> &services) : services_(services) { + } + virtual Result Perform(const ArgumentTuple& args) { + auto cb = ::std::tr1::get<0>(args); + cb(services_); + } + + private: + hidl_vec<hidl_string> services_; +}; + +Action<HardwareListFunction> HardwareList(const hidl_vec<hidl_string> &services) { + return MakeAction(new HardwareListAction(services)); +} + // Matcher for args using Android's Vector<String16> format // TODO: move it to some common testing library MATCHER_P(AndroidElementsAre, expected, "") { @@ -121,7 +167,7 @@ ACTION_P(Sleep, timeout) { class DumpsysTest : public Test { public: - DumpsysTest() : sm_(), dump_(&sm_), stdout_(), stderr_() { + DumpsysTest() : sm_(), hm_(), dump_(&sm_, &hm_), stdout_(), stderr_() { } void ExpectListServices(std::vector<std::string> services) { @@ -129,9 +175,22 @@ class DumpsysTest : public Test { for (auto& service : services) { services16.add(String16(service.c_str())); } + EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16)); } + void ExpectListHardwareServices(std::vector<std::string> services) { + hidl_vec<hidl_string> hidl_services; + hidl_services.resize(services.size()); + for (size_t i = 0; i < services.size(); i++) { + hidl_services[i] = services[i]; + } + + EXPECT_CALL(hm_, list(_)).WillRepeatedly(DoAll( + WithArg<0>(HardwareList(hidl_services)), + Return(Void()))); + } + sp<BinderMock> ExpectCheckService(const char* name, bool running = true) { sp<BinderMock> binder_mock; if (running) { @@ -175,8 +234,10 @@ class DumpsysTest : public Test { EXPECT_THAT(status, Eq(0)); } - void AssertRunningServices(const std::vector<std::string>& services) { - std::string expected("Currently running services:\n"); + void AssertRunningServices(const std::vector<std::string>& services, + const std::string &message = "Currently running services:") { + std::string expected(message); + expected.append("\n"); for (const std::string& service : services) { expected.append(" ").append(service).append("\n"); } @@ -204,12 +265,21 @@ class DumpsysTest : public Test { } ServiceManagerMock sm_; + HardwareServiceManagerMock hm_; Dumpsys dump_; private: std::string stdout_, stderr_; }; +TEST_F(DumpsysTest, ListHwServices) { + ExpectListHardwareServices({"Locksmith", "Valet"}); + + CallMain({"--hw"}); + + AssertRunningServices({"Locksmith", "Valet"}, "Currently running hardware services:"); +} + // Tests 'dumpsys -l' when all services are running TEST_F(DumpsysTest, ListAllServices) { ExpectListServices({"Locksmith", "Valet"}); |