Merge "dumpsys: add option to list hardware services."
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index 3476964..c5ae9d2 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -15,6 +15,8 @@
"libutils",
"liblog",
"libbinder",
+ "android.hidl.manager@1.0",
+ "libhidlbase"
],
clang: true,
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index f0e7200..860b7b4 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -45,8 +45,7 @@
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 @@
"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 @@
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 @@
} else if (!strcmp(longOptions[optionIndex].name, "help")) {
usage();
return 0;
+ } else if (!strcmp(longOptions[optionIndex].name, "hw")) {
+ listHwOnly = true;
}
break;
@@ -143,11 +171,17 @@
}
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 2534dde..20d515d 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 8ba0eba..b180c98 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 @@
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 7698ed5..e00444f 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -5,8 +5,12 @@
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 a61cb00..a66685d 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -44,6 +44,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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"});